MyBatis3 通用CRUD的研究[一]

本文介绍了一种基于MyBatis的自动CRUD解决方案,通过自定义基接口和动态SQL生成器,实现了无需XML配置即可完成基本的增删改查操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

MyBatis3提供了一种半自动化的ORM解决方案,比Hibernate这种全自动解决方案多了不少的灵活性和可操控性,试用了下感觉还不错,就是有个问题在于,MyBatis的所有处理都需要提供一个xml配置或者注解形式的语句,虽然动态SQL很强大,但是一般项目使用时,最多的CRUD操作,大多模式都是固定的

select:select * from [tablename]

insert:insert into [tablename]([field list]) values([values list])

update:update [tablename] set [field]=[value]... where [id]=[key]

delete:delete from [tablename] where [id]=[key]

这几种CRUD操作占了大部分,但是以MyBatis来说,每个表都要重新写一遍这几条相同的SQL又是一件非常烦人的事情,而且,那臃肿的xml配置文件看着就很烦啊

 

目的:

提供一个Mapper基接口,可以自动进行4种基本的CRUD操作,而不需要相应的xml文件

 

目前研究成果:

insert/update/delete操作可以非常完美的完成,select操作目前还需要多一条语句

 

首先,MyBatis使用名叫Mapper的接口来抽象化SQL操作,2种基本的方式:xml配置和注解配置

xml配置方式肯定没法达到自动继承的目的,放弃

来看看注解方式,MyBatis提供了2个注解标记 @Select 和 @SelectProvider,select标记只能处理字符串常量,放弃..

@SelectProvider可以使用一个SQL提供程序来生成相应的SQL语句,恩,这个很好很强大,我们可以设计一个基接口来生成我们需要的SQL

 

首先拿比较简单的Delete语句来看,我们的基接口可以这样写

  1. /**
  2. * MyBatis CRUD基接口
  3. * @author ALLEN.HU
  4. *
  5. * @param <T> 处理的POJO对象
  6. */
  7. public interface BaseMapper<T extends MyBatisPojo> {
  8. @DeleteProvider(type = CUDTemplate.class,method = "delete")
  9. public void delete(T obj);
  10. }
/** * MyBatis CRUD基接口 * @author ALLEN.HU * * @param <T> 处理的POJO对象 */ public interface BaseMapper<T extends MyBatisPojo> { @DeleteProvider(type = CUDTemplate.class,method = "delete") public void delete(T obj); }


想要从一个POJO上自动生成SQL语句需要2个必须的部分,一个是表名,一个是主键名

先做一个POJO的基类,方便以后调用,也方便泛型的处理 MyBatisPojo

  1. /**
  2. * MyBatis用POJO基类
  3. * 借用了JPA的注解标签 @Table和@Id 需要引入javax.persistence包(persistence.jar)
  4. * @author Allen.Hu
  5. *
  6. */
  7. public class MyBatisPojo implements Serializable{
  8. private static final long serialVersionUID = 1L;
  9. /**
  10. * 获取POJO对应的表名
  11. * 需要POJO中的属性定义@Table(name)
  12. * @return
  13. */
  14. public String tablename() {
  15. Table table = this.getClass().getAnnotation(Table.class);
  16. if(table != null)
  17. return table.name();
  18. else
  19. throw new RuntimeException("undefine POJO @Table, need Tablename(@Table)");
  20. }
  21. /**
  22. * 获取POJO对应的主键名称
  23. * 需要POJO中的属性定义@Id
  24. * @return
  25. */
  26. public String id() {
  27. for(Field field : this.getClass().getFields()) {
  28. if(field.isAnnotationPresent(Id.class))
  29. return field.getName();
  30. }
  31. throw new RuntimeException("undefine POJO @Id");
  32. }
  33. }
/** * MyBatis用POJO基类 * 借用了JPA的注解标签 @Table和@Id 需要引入javax.persistence包(persistence.jar) * @author Allen.Hu * */ public class MyBatisPojo implements Serializable{ private static final long serialVersionUID = 1L; /** * 获取POJO对应的表名 * 需要POJO中的属性定义@Table(name) * @return */ public String tablename() { Table table = this.getClass().getAnnotation(Table.class); if(table != null) return table.name(); else throw new RuntimeException("undefine POJO @Table, need Tablename(@Table)"); } /** * 获取POJO对应的主键名称 * 需要POJO中的属性定义@Id * @return */ public String id() { for(Field field : this.getClass().getFields()) { if(field.isAnnotationPresent(Id.class)) return field.getName(); } throw new RuntimeException("undefine POJO @Id"); } }

然后是动态sql的生成类 CUDTemplate

  1. import static org.apache.ibatis.jdbc.SqlBuilder.*;
  2. public class CUDTemplate<T extends MyBatisPojo> {
  3. public String delete(T obj) {
  4. String idname = obj.id();
  5. BEGIN();
  6. DELETE_FROM(obj.tablename());
  7. WHERE(idname + "=#{" + idname + "}");
  8. return SQL();
  9. }
  10. }
import static org.apache.ibatis.jdbc.SqlBuilder.*; public class CUDTemplate<T extends MyBatisPojo> { public String delete(T obj) { String idname = obj.id(); BEGIN(); DELETE_FROM(obj.tablename()); WHERE(idname + "=#{" + idname + "}"); return SQL(); } }


有了这三个简单的类/接口,在实际使用中,就不再需要烦人的xml配置了,继承MyBatisPojo的实体配合继承BaseMapper的映射器,就能直接使用对应的delete方法了

假设表 test

  1. create table "RSMNG"."dbo"."test"(
  2. "id" int identity not null,
  3. "text" varchar(100) not null,
  4. constraint "PK_test" primary key ("id")
  5. )
create table "RSMNG"."dbo"."test"( "id" int identity not null, "text" varchar(100) not null, constraint "PK_test" primary key ("id") )

就2个字段,一个id作为主键,一个text

对应的Pojo类

  1. @Table(name = "test")
  2. public class Test extends MyBatisPojo {
  3. @Id
  4. private Integer id;
  5. @Column
  6. private String text;
  7. public void setId(Integer id) {
  8. this.id = id;
  9. }
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setText(String text) {
  14. this.text = text;
  15. }
  16. public String getText() {
  17. return text;
  18. }
  19. }
@Table(name = "test") public class Test extends MyBatisPojo { @Id private Integer id; @Column private String text; public void setId(Integer id) { this.id = id; } public Integer getId() { return id; } public void setText(String text) { this.text = text; } public String getText() { return text; } }


对应的Mapper TestMapper

  1. /**
  2. * 从BaseMapper继承的话,不需要再去实现基本方法
  3. */
  4. public interface TestMapper extends BaseMapper<Test> {
  5. }
/** * 从BaseMapper继承的话,不需要再去实现基本方法 */ public interface TestMapper extends BaseMapper<Test> { }


实际使用时,只需要调用testMapper.delete(Test)函数就能执行相应的删除动作了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值