前段时间了解到Spring JPA,感觉挺好用,但其依赖于Hibernate,本人看到Hibernate就头大(不是说Hibernate不好哈,而是进阶太难),于是做了一个迷你版的Mybatis JPA.
代码地址(github):
代码地址(gitee):
QQ交流群:246912326
因为版本更新,可能会导致博客与代码不对应,强烈建议阅读代码仓库的wiki文档
maven
com.littlenb mybatis-jpa 2.1.1
1.1 版本说明
v2.0.1:纯净版的resultTypePlugin
v2.1.0:在v2.0.1基础上,增加SQL构建,InsertDefinition|UpdateDifinition
v2.1.1:增加自定义枚举值,ICodeEnum,@CodeEnum,IntCodeEnumTypeHandler,StringCodeEnumTypeHandler
1.2 工作模式
1.)mybatis-jpa 是基于Mybatis的增强插件,没有对依赖包(源代码)造成污染.
2.)ResultTypePlugin在运行时拦截,每个被拦截的方法会在初次调用时完成解析.
3.)mybatis-jpa SQL的解析和Statement的注册时机,是在Spring applicationContext初始化完成时,只会解析一次.
4.)由mybatis-jpa 解析的Mapper接口中定义的方法(method),将被注册到Mybatis Configuration中,即Mapper的代理和注入由依旧由Mybatis和Spring构建和管理,不影响原有的代码模式和工作模式.
1.3 约定
1.)Entity实体类需使用@Entity或@Table注解标记,类中字段类型不允许使用基本数据类型(如:使用Integer定义整形而不是int);
2.)ResultTypePlugin支持结果集的嵌套,SQL的构建(InsertDefinition|UpdateDifinition)会忽略实体类的嵌套.
3.)按照Mybatis约定,Enum枚举类型默认以 () 解析,若要解析为enum.ordinal(),需使用注解@Enumrated(value = EnumType.ORDINAL)标识.
4.)使用自定义枚举值,枚举类型需实现ICodeEnum接口,并使用注解@CodeEnum标记Field.@CodeEnum优先级高于@Enumrated.
插件清单
-
ResultTypePlugin
-
DefinitionStatementScanner
2.1 ResultTypePlugin
对于常规的结果映射,不需要再构建ResultMap,ResultTypePlugin增加了Mybatis对结果映射(JavaBean/POJO)中JPA注解的处理。
映射规则:
-
名称匹配默认为驼峰(Java Field)与下划线(SQL Column)
-
使用@Column注解中name属性指定SQL Column
-
使用@Transient注解标记非持久化字段(不需要结果集映射的字段)
类型处理:
-
Boolean-->BooleanTypeHandler
-
Enum默认为EnumTypeHandler
使用@Enumerated(EnumType.ORDINAL) 指定为 EnumOrdinalTypeHandler
-
Enum实现ICodeEnum接口实现自定义枚举值
使用@CodeEnum(CodeType.INT) 指定为 IntCodeEnumTypeHandler
或@CodeEnum(CodeType.STRING) 指定为 StringCodeEnumTypeHandler
@CodeEnum 优先级 高于 @Enumerated
结果集嵌套:
- 支持OneToOne
- 支持OneToMany
e.g.
mybatis.xml
JavaBean
@Entitypublic class UserArchive {//@Id private Long userId;// /** 默认驼峰与下划线转换 */ private String userName;// /** 枚举类型 */ @Enumerated(EnumType.ORDINAL) private SexEnum sex;// /** 枚举类型,自定义值 */ @CodeEnum(CodeType.INT) private PoliticalEnum political;// /** 属性名与列名不一致 */ @Column(name = "gmt_create") private Date createTime;// }//
mapper.xml
DefinitionStatementScanner
注册MappedStatement,基于注解,仅支持Insert和Update。
@InsertDefinition:
- selective: 默认值false(处理null属性)
@UpdateDefinition:
-
selective: 默认值false(处理null属性)
-
where: SQL condition
e.g.
Spring 容器初始化完成后执行
@Servicepublic class DefinitionStatementInit { @Autowired private SqlSessionFactory sqlSessionFactory; @PostConstruct public void init() { Configuration configuration = sqlSessionFactory.getConfiguration(); StatementBuildable statementBuildable = new DefinitionStatementBuilder(configuration); DefinitionStatementScanner.Builder builder = new DefinitionStatementScanner.Builder(); DefinitionStatementScanner definitionStatementScanner = builder.configuration(configuration).basePackages(new String[]{"com.mybatis.jpa.mapper"}) .statementBuilder(statementBuildable).build(); definitionStatementScanner.scan(); }}
Mapper
@Mapper@Repositorypublic interface UserUpdateMapper { @InsertDefinition(selective = true) int insert(User user); @UpdateDefinition(selective = true, where = " user_id = #{userId}") int updateById(User user);}
更多示例请查看test目录代码。
如果你想深入了解,项目代码目录还算清晰,源码中有大量必要的注释,你会发现有部分英文注释,不要慌,是我写的,现在感觉有些代码用英文描述反而会简单一些,用中文反而不能够被很好的理解.
因个人能力有限,如有不足之处,请多包涵,欢迎交流/指正.