如今愈來愈流行基於 SpringBoot 開發 Web 應用,其中利用 Mybatis 做爲數據庫 CRUD 操做已成爲主流。樓主以 MySQL 爲例,總結了九大類使用 Mybatis 操做數據庫 SQL 小技巧分享給你們。html
利用 limit 設置每頁 offset 偏移量和每頁 size 大小。java
select * from sys_user u LEFT JOIN sys_user_site s ON u.user_id = s.user_id LEFT JOIN sys_dept d ON d.dept_id = s.dept_id LEFT JOIN sys_emailinfo e ON u.user_id = e.userid AND e.MAIN_FLAG = 'Y' <where> <include refid="userCondition"/> </where> limit #{offset}, #{limit}
<sql id="columns"> id,title,content,original_img,is_user_edit,province_id,status,porder </sql>
查詢 select 語句引用 columns:mysql
<select id="selectById" resultMap="RM_MsShortcutPanel"> seelct <include refid="columns"/> from cms_self_panel where id = #{_parameter} </select>
利用 mybatis 的 collection 標籤,能夠在每次查詢文章主體同時經過 queryparaminstancelist 級聯查詢出關聯表數據。git
<resultMap id="BaseResultMap" type="com.unicom.portal.pcm.entity.ArticleEntity"> <id column="id" jdbcType="BIGINT" property="id"/> <collection property="paramList" column="id" select="queryparaminstancelist"/> </resultMap>
queryparaminstancelist 的 sql 語句程序員
<select id="queryparaminstancelist" resultMap="ParamInstanceResultMap"> select * from `cms_article_flow_param_instance` where article_id=#{id} </select>
利用 mybatis 的 association 標籤,一對一查詢關聯表數據。github
<resultMap id="BaseResultMap" type="com.unicom.portal.pcm.entity.ArticleEntity"> <association property="articleCount" javaType="com.unicom.portal.pcm.entity.MsArticleCount"/> </resultMap>
查詢sql語句:web
MsArticlecount 實體對象的屬性值能夠從 上面的 select 後的 sql 字段進行匹配映射獲取。spring
利用 foreach 遍歷 array 集合的參數,拼成 in 查詢條件sql
<foreach collection="array" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach>
select r.*, (select d.org_name from sys_dept d where d.dept_id = r.dept_id) deptName from sys_role r <where> r.wid = #{wid} <if test="roleName != null and roleName.trim() != ''"> and r.`role_name` like concat('%',#{roleName},'%') </if> <if test="status != null and status.trim() != ''"> and r.`status` = #{status} </if> </where>
<choose> <when test="sidx != null and sidx.trim() != ''"> order by r.${sidx} ${order} </when> <otherwise> order by r.role_id asc </otherwise> </choose>
_parameter 參數的含義數據庫
「
當 Mapper、association、collection 指定只有一個參數時進行查詢時,可使用 _parameter,它就表明了這個參數。
另外,當使用 Mapper指定方法使用 @Param 的話,會使用指定的參數值代替。
SELECT id, grp_no grpNo, province_id provinceId, status FROM tj_group_province <where> ... <if test="_parameter!=null"> and grp_no = #{_parameter} </if> </where>
<update id="updateById"> UPDATE cms_label <set> <if test="labelGroupId != null"> label_group_id = #{labelGroupId}, </if> dept_id = #{deptId}, <if test="recommend != null"> is_recommend = #{recommend}, </if> </set> WHERE label_id = #{labelId} </update
若是 Mybatis-Plus 是扳手,那 Mybatis Generator 就是生產扳手的工廠。
MyBatis 是一種操做數據庫的 ORM 框架,提供一種 Mapper 類,支持讓你用 java 代碼進行增刪改查的數據庫操做,省去了每次都要手寫 sql 語句的麻煩。可是有一個前提,你得先在 xml 中寫好 sql 語句,也是很麻煩的。
Mybatis-Plus 的存在就是爲了稍稍彌補 Mybatis 的不足。
在咱們使用 Mybatis 時會發現,每當要寫一個業務邏輯的時候都要在 DAO 層寫一個方法,再對應一個 SQL,即便是簡單的條件查詢、即便僅僅改變了一個條件都要在 DAO層新增一個方法,針對這個問題,Mybatis-Plus 就提供了一個很好的解決方案:lambda 表達式,它可讓咱們避免許多重複性的工做。
想一想 Mybatis 官網提供的 CRUD 例子吧,基本上 xml 配置佔據了絕大部分。而用 Lambda 表達式寫的 CRUD 代碼很是簡潔,真正作到零配置,不須要在 xml 或用註解(@Select)寫大量原生 SQL 代碼。
LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getSex, 0L) .like(UserEntity::getUserName, "dun"); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like全包含關鍵字查詢::" + u.getUserName()));
Java中的 lambda 表達式實質上是一個匿名方法,但該方法並不是獨立執行,而是用於實現由函數式接口定義的惟一抽象方法。
使用 lambda 表達式時,會建立實現了函數式接口的一個匿名類實例,如 Java8 中的線程 Runnable 類實現了函數接口:@FunctionalInterface。
@FunctionalInterface public interface Runnable { public abstract void run(); }
日常咱們執行一個 Thread 線程:
new Thread(new Runnable() { @Override public void run() { System.out.println("xxxx"); } }).start();
若是用 lambda 會很是簡潔,一行代碼搞定。
new Thread(()-> System.out.println("xxx")).start();
因此在某些場景下使用 lambda 表達式真的能減小 java 中一些冗長的代碼,增長代碼的優雅性。
警告:
不支持以及不同意在 RPC 調用中把 Wrapper 進行傳輸。
「
Wrapper 很重 傳輸 Wrapper 能夠類比爲你的 controller 用 map 接收值(開發一時爽,維護火葬場) 正確的 RPC 調用姿式是寫一個 DTO 進行傳輸,被調用方再根據 DTO 執行相應的操做 咱們拒絕接受任何關於 RPC 傳輸 Wrapper 報錯相關的 issue 甚至 pr。
從上圖,咱們瞭解到 AbstractWrapper 的實際上實現了五大接口:
@FunctionalInterface public interface ISqlSegment extends Serializable { /** * SQL 片斷 */ String getSqlSegment(); }
經常使用的 where 條件表達式 eq、like、in、ne、gt、ge、lt、le。
@Override public Children in(boolean condition, R column, Collection<?> coll) { return doIt(condition, () -> columnToString(column), IN, inExpression(coll)); } public Children notIn(boolean condition, R column, Collection<?> coll) public Children inSql(boolean condition, R column, String inValue) public Children notInSql(boolean condition, R column, String inValue) public Children groupBy(boolean condition, R... columns) public Children orderBy(boolean condition, boolean isAsc, R... columns) public Children eq(boolean condition, R column, Object val) public Children ne(boolean condition, R column, Object val) public Children gt(boolean condition, R column, Object val) public Children ge(boolean condition, R column, Object val) public Children lt(boolean condition, R column, Object val) public Children le(boolean condition, R column, Object val) ... /** * 普通查詢條件 * * @param condition 是否執行 * @param column 屬性 * @param sqlKeyword SQL 關鍵詞 * @param val 條件值 */ protected Children addCondition(boolean condition, R column, SqlKeyword sqlKeyword, Object val) { return doIt(condition, () -> columnToString(column), sqlKeyword, () -> formatSql("{0}", val)); }
lambda 這麼好用的祕訣在於 SQL 片斷函數接口:ISqlSegment,咱們在 doIt 方法找到 ISqlSegment 對象參數,翻開 ISqlSegment 源碼,發現它真實的廬山真面目,原來是基於 Java 8 的函數接口 @FunctionalInterface 實現!
ISqlSegment 就是對 where 中的每一個條件片斷進行組裝。
/** * 對sql片斷進行組裝 * * @param condition 是否執行 * @param sqlSegments sql片斷數組 * @return children */ protected Children doIt(boolean condition, ISqlSegment... sqlSegments) { if (condition) { expression.add(sqlSegments); } return typedThis; } @FunctionalInterface public interface ISqlSegment extends Serializable { /** * SQL 片斷 */ String getSqlSegment(); }
從 MergeSegments 類中,咱們找到 getSqlSegment 方法,其中代碼片斷
sqlSegment = normal.getSqlSegment() + groupBy.getSqlSegment() + having.getSqlSegment() + orderBy.getSqlSegment()
這段代碼代表,一條完整的 where 條件 SQL 語句,最終由 normal SQL 片斷,groupBy SQL 片斷,having SQL 片斷,orderBy SQL 片斷拼接而成。
@Getter @SuppressWarnings("serial") public class MergeSegments implements ISqlSegment { private final NormalSegmentList normal = new NormalSegmentList(); private final GroupBySegmentList groupBy = new GroupBySegmentList(); private final HavingSegmentList having = new HavingSegmentList(); private final OrderBySegmentList orderBy = new OrderBySegmentList(); @Getter(AccessLevel.NONE) private String sqlSegment = StringPool.EMPTY; @Getter(AccessLevel.NONE) private boolean cacheSqlSegment = true; public void add(ISqlSegment... iSqlSegments) { List<ISqlSegment> list = Arrays.asList(iSqlSegments); ISqlSegment firstSqlSegment = list.get(0); if (MatchSegment.ORDER_BY.match(firstSqlSegment)) { orderBy.addAll(list); } else if (MatchSegment.GROUP_BY.match(firstSqlSegment)) { groupBy.addAll(list); } else if (MatchSegment.HAVING.match(firstSqlSegment)) { having.addAll(list); } else { normal.addAll(list); } cacheSqlSegment = false; } @Override public String getSqlSegment() { if (cacheSqlSegment) { return sqlSegment; } cacheSqlSegment = true; if (normal.isEmpty()) { if (!groupBy.isEmpty() || !orderBy.isEmpty()) { sqlSegment = groupBy.getSqlSegment() + having.getSqlSegment() + orderBy.getSqlSegment(); } } else { sqlSegment = normal.getSqlSegment() + groupBy.getSqlSegment() + having.getSqlSegment() + orderBy.getSqlSegment(); } return sqlSegment; } }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency>
@NoArgsConstructor @AllArgsConstructor(access = AccessLevel.PACKAGE) @SuperBuilder(toBuilder = true) @Data public class BaseEntity { @TableField(value = "created_tm", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createdTm; @TableField(value = "created_by", fill = FieldFill.INSERT) private String createdBy; @TableField(value = "modified_tm", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime modifiedTm; @TableField(value = "modified_by", fill = FieldFill.INSERT_UPDATE) private String modifiedBy; }
@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor(access = AccessLevel.PACKAGE) @SuperBuilder(toBuilder = true) @Data @TableName("sys_user") public class UserEntity extends BaseEntity{ private Long userId; private String userName; private Integer sex; private Integer age; private String mobile; }
Mapper 操做類
List<UserDTO> selectUsers(); UserEntity selectByIdOnXml(long userId); @Results(id = "userResult", value = { @Result(property = "user_id", column = "userId", id = true), @Result(property = "userName", column = "user_name"), @Result(property = "sex", column = "sex"), @Result(property = "mobile", column = "mobile"), @Result(property = "age", column = "age") }) @Select("select * from sys_user where user_id = #{id}") UserEntity selectByIdOnSelectAnnotation(@Param("id") long id); @SelectProvider(type = UserSqlProvider.class, method = "selectById") @ResultMap("BaseResultMap") UserEntity selectByIdOnSelectProviderAnnotation(long id); @Select("select * from sys_user where user_id = #{id} and user_name=#{userName}") @ResultMap("BaseResultMap") UserEntity selectByIdOnParamAnnotation(@Param("id") long id, @Param("userName") String uerName);
Mapper 表映射文件
<mapper namespace="com.dunzung.mybatisplus.query.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.dunzung.mybatisplus.query.entity.UserEntity"> <id column="user_id" property="userId"/> <result column="user_name" property="userName"/> <result column="sex" property="sex"/> <result column="age" property="age"/> <result column="mobile" property="mobile"/> </resultMap> <resultMap id="RelationResultMap" type="com.dunzung.mybatisplus.query.entity.UserDTO" extends="BaseResultMap"> <association property="card" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.CardMapper.selectCardByUserId"/> <collection property="orders" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.OrderMapper.selectOrders"/> </resultMap> <select id="selectUsers" resultMap="RelationResultMap"> select * from sys_user </select> <select id="selectByIdOnXml" resultMap="BaseResultMap"> select * from sys_user where user_id = #{userId} </select> </mapper>
@Data @TableName("sys_user_card") public class CardEntity { private Long cardId; private String cardCode; private Long userId; }
Mapper 操做類
@Mapper public interface OrderMapper extends BaseMapper<OrderEntity> { }
Mapper 表映射文件
<mapper namespace="com.dunzung.mybatisplus.query.mapper.OrderMapper"> <resultMap id="BaseResultMap" type="com.dunzung.mybatisplus.query.entity.OrderEntity"> <id column="order_id" property="orderId"/> <result column="order_name" property="orderName"/> <result column="user_id" property="userId"/> <result column="price" property="price"/> <result column="created_tm" property="createdTm"/> </resultMap> <select id="selectOrders" resultMap="BaseResultMap"> select * from biz_order where user_id = #{userId} </select> </mapper>
@Data @TableName("biz_order") public class OrderEntity { private Long orderId; private String orderName; private Integer userId; private Date createdTm; private Integer price; }
Mapper 操做類
@Mapper public interface CardMapper extends BaseMapper<CardEntity> { }
Mapper 表映射文件
<mapper namespace="com.dunzung.mybatisplus.query.mapper.CardMapper"> <resultMap id="BaseResultMap" type="com.dunzung.mybatisplus.query.entity.CardEntity"> <id column="card_id" property="cardId"/> <result column="card_code" property="cardCode"/> <result column="user_id" property="userId"/> </resultMap> <select id="selectCardByUserId" resultMap="BaseResultMap"> select * from sys_user_card where user_id = #{userId} </select> </mapper>
LambdaQueryWrapper 四種不一樣的 lambda 構造方法
LambdaQueryWrapper<UserEntity> lambda = new QueryWrapper<UserEntity>().lambda();
LambdaQueryWrapper<UserEntity> lambda = new LambdaQueryWrapper<>();
LambdaQueryWrapper<UserEntity> lambda = Wrappers.lambdaQuery();
List<UserEntity> users = new LambdaQueryChainWrapper<UserEntity>(userMapper) .like(User::getName, "雨").ge(User::getAge, 20).list();
筆者推薦使用 Wrappers 的靜態方法 lambdaQuery 構建 LambdaQueryWrapper 條件構造器。
爲了 Debug 調試方便,須要在 application.yml 啓動文件開啓 Mybatis-Plus SQL 執行語句全棧打印:
#mybatis mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
執行效果以下:
@Test public void testLambdaQueryOfEq() { //eq查詢 //至關於 select * from sys_user where user_id = 1 LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getUserId, 1L); UserEntity user = userMapper.selectOne(lqw); System.out.println("eq查詢::" + user.getUserName()); }
eq 查詢等價於原生 sql 的等值查詢。
select * from sys_user where user_id = 1
@Test public void testLambdaQueryOfIn() { List<Long> ids = Arrays.asList(1L, 2L); LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.in(UserEntity::getUserId, ids); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("in查詢::" + u.getUserName())); }
in 查詢等價於原生 sql 的 in 查詢
select * from sys_user where user_id in (1,2)
@Test public void testLambdaQueryOfLikeAll() { LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getSex, 0L) .like(UserEntity::getUserName, "dun"); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like全包含關鍵字查詢::" + u.getUserName())); }
like 查詢等價於原生 sql 的 like 全通配符模糊查詢。
select * from sys_user where sex = 0 and user_name like '%dun%'
@Test public void testLambdaQueryOfLikeRight() { LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getSex, 0L) .likeRight(UserEntity::getUserName, "dun"); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like Right含關鍵字查詢::" + u.getUserName())); }
likeRight 查詢至關於原生 sql 的 like 右通配符模糊查詢。
select * from sys_user where sex = 0 and user_name like 'dun%'
@Test public void testLambdaQueryOfLikeLeft() { LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getSex, 0L) .likeLeft(UserEntity::getUserName, "zung"); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like Left含關鍵字查詢::" + u.getUserName())); }
likeLeft 查詢至關於原生 sql 的 like 左通配符模糊查詢。
select * from sys_user where sex = 0 and user_name like '%zung'
條件判斷查詢相似於 Mybatis 的 if 標籤,第一個入參 boolean condition 表示該條件是否加入最後生成的 sql 中。
@Test public void testLambdaQueryOfBoolCondition() { UserEntity condition = UserEntity.builder() .sex(1) .build(); //eq 或 like 條件判斷查詢 LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(condition.getSex() != null, UserEntity::getSex, 0L) // 知足 bool 判斷,是否進查詢按字段 userName 查詢 .like(condition.getUserName() != null, UserEntity::getUserName, "dun"); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like查詢::" + u.getUserName())); }
@Test public void testLambdaQueryOfOr_And() { LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.eq(UserEntity::getSex, 0L) .and(wrapper->wrapper.eq(UserEntity::getUserName,"dunzung") .or().ge(UserEntity::getAge, 50)); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("like查詢::" + u.getUserName())); }
上面實例查詢等價於原生 sql 查詢:
select * from sys_user where sex = 0 and (use_name = 'dunzung' or age >=50)
@Test public void testLambdaPage() { //PageHelper分頁查詢 //至關於 select * from sys_user limit 0,2 int pageNumber = 0; int pageSize = 2; PageHelper.startPage(pageNumber + 1, pageSize); LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery(); lqw.orderByAsc(UserEntity::getAge) .orderByDesc(UserEntity::getMobile); List<UserEntity> userList = userMapper.selectList(lqw); userList.forEach(u -> System.out.println("page分頁查詢::" + u.getUserName())); }
上面實例查詢等價於原生 sql 分頁查詢:
select * from sys_user order by age desc,mobile desc limit 0,2
另外,Mybatis-Plus 自帶分頁組件,BaseMapper 接口提供兩種分頁方法來實現物理分頁。
IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper); IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);
注意,Mybatis-Plus 自帶分頁組件時,須要配置 PaginationInterceptor 分頁插件。
@Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }
@Test public void testLambdaUpdate() { LambdaUpdateWrapper<UserEntity> luw = Wrappers.lambdaUpdate(); luw.set(UserEntity::getUserName, "dunzung01") .set(UserEntity::getSex, 1); luw.eq(UserEntity::getUserId, 1); userMapper.update(null, luw); }
Association 標籤適用於表和表之間存在一對一的關聯關係,如用戶和身份證存在一我的只會有一個身份證號,反過來也成立。
@Test public void testOnAssociationTag() { List<UserDTO> userList = userMapper.selectUsers(); userList.forEach(u -> System.out.println(u.getUserName())); }
XML配置
<resultMap id="RelationResultMap" type="com.dunzung.mybatisplus.query.entity.UserDTO" extends="BaseResultMap"> <association property="card" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.CardMapper.selectCardByUserId"/> </resultMap>
Collection 標籤適用於表和表之間存在一對多的關聯關係,如用戶和訂單存在一我的能夠購買多個物品,產生多個購物訂單。
@Test public void testOnCollectionTag() { List<UserDTO> userList = userMapper.selectUsers(); userList.forEach(u -> System.out.println(u.getUserName())); }
XML配置
<resultMap id="RelationResultMap" type="com.dunzung.mybatisplus.query.entity.UserDTO" extends="BaseResultMap"> <collection property="orders" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.OrderMapper.selectOrders"/> </resultMap>
注意 Association 和 Collection 前後關係,在編寫 ResultMap 時,association 在前,collection 標籤在後。
<resultMap id="RelationResultMap" type="com.dunzung.mybatisplus.query.entity.UserDTO" extends="BaseResultMap"> <association property="card" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.CardMapper.selectCardByUserId"/> <collection property="orders" column="{userId,user_id}" select="com.dunzung.mybatisplus.query.mapper.OrderMapper.selectOrders"/> </resultMap>
若是兩者顛倒順序會提示錯誤。
MetaObjectHandler元對象字段填充器的填充原理是直接給 entity 的屬性設置值,提供默認方法的策略均爲:
「
若是屬性有值則不覆蓋,若是填充值爲 null 則不填充,字段必須聲明 TableField 註解,屬性 fill 選擇對應策略,該聲明告知 Mybatis-Plus 須要預留注入 SQL字段。 TableField 註解則是指定該屬性在對應狀況下必有值,若是無值則入庫會是 null。
自定義填充處理器 MyMetaObjectHandler 在 Spring Boot 中須要聲明 @Component 或 @Bean 注入,要想根據註解 FieldFill.xxx,如:
@TableField(value = "created_tm", fill = FieldFill.INSERT) private LocalDateTime createdTm; @TableField(value = "modified_tm", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime modifiedTm;
和字段名以及字段類型來區分必須使用父類的 setInsertFieldValByName 或者 setUpdateFieldValByName 方法,不須要根據任何來區分可使用父類的 setFieldValByName 方法 。
/** * 屬性值填充 Handler * * @author 猿芯 * @since 2021/3/30 */ @Component public class FillMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setInsertFieldValByName("createdTm", LocalDateTime.now(), metaObject); this.setInsertFieldValByName("createdBy", MvcContextHolder.getUserName(), metaObject); this.setFieldValByName("modifiedTm", LocalDateTime.now(), metaObject); this.setFieldValByName("modifiedBy", MvcContextHolder.getUserName(), metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setUpdateFieldValByName("modifiedTm", LocalDateTime.now(), metaObject); this.setUpdateFieldValByName("modifiedBy", MvcContextHolder.getUserName(), metaObject); } }
通常 FieldFill.INSERT 用父類的 setInsertFieldValByName 方法更新建立屬性(建立人、建立時間)值;FieldFill.INSERT_UPDATE 用父類的 setUpdateFieldValByName 方法更新修改屬性(修改人、修改時間)值;若是想讓諸如 FieldFill.INSERT 或 FieldFill.INSERT_UPDATE 任什麼時候候不起做用,用父類的 setFieldValByName 設置屬性(建立人、建立時間、修改人、修改時間)值便可。
使用 Wrapper 自定義 SQL 須要 mybatis-plus 版本 >= 3.0.7 ,param 參數名要麼叫 ew,要麼加上註解 @Param(Constants.WRAPPER) ,使用 ${ew.customSqlSegment} 不支持 Wrapper 內的 entity生成 where 語句。
註解方式
@Select("select * from mysql_data ${ew.customSqlSegment}") List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
XML配置
List<MysqlData> getAll(Wrapper ew); <select id="getAll" resultType="MysqlData"> SELECT * FROM mysql_data ${ew.customSqlSegment} </select>
經過上面豐富的舉例詳解以及剖析 lambda 底層實現原理,想必你們會問:」 lambda 表達式彷佛只支持單表操做?」
據我對 Mybatis-Plus 官網的瞭解,目前確實是這樣。依筆者實際運用經驗來看,其實程序員大部分開發的功能基本上都是針對單表操做的,Lambda 表達式的優點在於幫助開發者減小在 XML 編寫大量重複的 CRUD 代碼,這點是很是重要的 nice 的。很顯然,Lambda 表達式對於提升程序員的開發效率是不言而喻的,我想這點也是我做爲程序員很是喜歡 Mybatis-Plus 的一個重要緣由。
可是,若是涉及對於多表之間的關聯查詢,lambda 表達式就顯得力不從心了,由於 Mybatis-Plus 並無提供相似於 join 查詢的條件構造器。
lambda 表達式優勢:
lambda 表達式缺點:
Mybatis-Plus 推出的 lambda 表達式致力於構建複雜的 where 查詢構造器式並非銀彈,它能夠解決你實際項目中 80% 的開發效率問題,可是針對一些複雜的大 SQL 查詢條件支持地並很差,例如一些複雜的 SQL 報表統計查詢。
因此,筆者推薦單表操做用 lambda 表達式,查詢推薦用 LambdaQueryWrapper,更新用 LambdaUpdateWrapper;多表操做仍是老老實實寫一些原生 SQL ,至於原生 SQL 寫在哪裏? Mapper 文件或者基於註解,如 @Select 都是能夠的。
做者:猿芯
來源: https://www.toutiao.com/i6951...