前段时间了解到Spring JPA,感觉挺好用,但其依赖于Hibernate,本人看到Hibernate就头大(不是说Hibernate不好哈,而是进阶太难),于是做了一个迷你版的Mybatis JPA.

代码地址(github): https://github.com/svili365/mybatis-jpa

代码地址(gitee): https://gitee.com/svili/mybatis-jpa

QQ交流群:246912326

因为版本更新,可能会导致博客与代码不对应,强烈建议阅读代码仓库的wiki文档

maven

<dependency>
<groupId>com.littlenb</groupId>
<artifactId>mybatis-jpa</artifactId>
<version>2.1.1</version>
</dependency>

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.name() 解析,若要解析为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

<configuration>
<plugins>
<plugin interceptor="com.mybatis.jpa.plugin.ResultTypePlugin">
</plugin>
</plugins>
</configuration>

JavaBean

@Entity
public class UserArchive {// <resultMap id="xxx" type="userArchive"> @Id
private Long userId;// <id property="id" column="user_id" /> /** 默认驼峰与下划线转换 */
private String userName;// <result property="username" column="user_name"/> /** 枚举类型 */
@Enumerated(EnumType.ORDINAL)
private SexEnum sex;// <result property="sex" column="sex" typeHandler=EnumOrdinalTypeHandler/> /** 枚举类型,自定义值 */
@CodeEnum(CodeType.INT)
private PoliticalEnum political;// <result property="political" column="political" typeHandler=IntCodeEnumTypeHandler/> /** 属性名与列名不一致 */
@Column(name = "gmt_create")
private Date createTime;// <result property="createTime" column="gmt_create"/>
}// </resultMap>

mapper.xml

<!-- in xml,declare the resultType -->
<select id="selectById" resultType="userArchive">
SELECT * FROM t_sys_user_archive WHERE user_id = #{userId}
</select>

DefinitionStatementScanner

注册MappedStatement,基于注解,仅支持Insert和Update。

@InsertDefinition:

  • selective: 默认值false(处理null属性)

@UpdateDefinition:

  • selective: 默认值false(处理null属性)

  • where: SQL condition

e.g.

Spring 容器初始化完成后执行

@Service
public 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
@Repository
public interface UserUpdateMapper { @InsertDefinition(selective = true)
int insert(User user); @UpdateDefinition(selective = true, where = " user_id = #{userId}")
int updateById(User user);
}

更多示例请查看test目录代码。

如果你想深入了解,项目代码目录还算清晰,源码中有大量必要的注释,你会发现有部分英文注释,不要慌,是我写的,现在感觉有些代码用英文描述反而会简单一些,用中文反而不能够被很好的理解.

代码的构建思路及代码解析,见博文:http://www.cnblogs.com/svili/p/7232323.html

因个人能力有限,如有不足之处,请多包涵,欢迎交流/指正.

Mybatis JPA 代码构建的更多相关文章

  1. Mybatis JPA 插件简介

    前段时间了解到Spring JPA,感觉挺好用,但其依赖于Hibernate,本人看到Hibernate就头大(不是说Hibernate不好哈,而是进阶太难),于是做了一个迷你版的Mybatis JP ...

  2. Mybatis jpa mini 代码解析

    源码地址(git):https://github.com/LittleNewbie/mybatis-jpa 一.Mybatis简介 mybatis中文官方文档:http://www.mybatis.o ...

  3. Mybatis JPA 插件简介(v2.1.0)

    相比之前的版本(v1.1.0),此版本(v2.1.0)做了较大的改动. 项目地址: github https://github.com/cnsvili/mybatis-jpa gitee https: ...

  4. 使用spring+mybatis+atomikos+tomcat构建分布式事务

    本文通过一个demo,介绍如何使用spring+mybatis+atomikos+tomcat构建在一个事务中涉及两个数据源的web应用. demo功能:实现一个能成功提交和回滚的涉及两个数据库数据源 ...

  5. 基于Spring + Spring MVC + Mybatis 高性能web构建

    基于Spring + Spring MVC + Mybatis 高性能web构建 一直想写这篇文章,前段时间 痴迷于JavaScript.NodeJs.AngularJs,做了大量的研究,对前后端交互 ...

  6. Springboot+MyBatis+JPA集成

      1.前言 Springboot最近可谓是非常的火,本人也在项目中尝到了甜头.之前一直使用Springboot+JPA,用了一段时间发现JPA不是太灵活,也有可能是我不精通JPA,总之为了多学学Sp ...

  7. 集成Springboot+MyBatis+JPA

    1.前言 Springboot最近可谓是非常的火,本人也在项目中尝到了甜头.之前一直使用Springboot+JPA,用了一段时间发现JPA不是太灵活,也有可能是我不精通JPA,总之为了多学学Spri ...

  8. 基于eclipse的mybatis映射代码自动生成的插件

    基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...

  9. 基于eclipse的mybatis映射代码自动生成的插件http://blog.csdn.net/fu9958/article/details/7521681

    基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...

随机推荐

  1. css简单了解

    今天主要是说一下css样式表!HTML结合他使用可以是HTML页面变得很绚丽多彩! 先简单介绍一下为什么要使用CSS(Cascading Style Sheets)层叠样式表! 1.因为CSS样式表可 ...

  2. Bootstrap 常用组件汇总

    Bootstrap 官方文档:http://www.bootcss.com/ Bootstrap Multiselect 多选下拉组件 官方文档:http://www.kuitao8.com/demo ...

  3. webpack 插件拾趣 (1) —— webpack-dev-server

    结束了一季的忙碌,我这封笔已久的博客也终究该从春困的咒印中复苏,想来写些实用易读的作为开篇,自然是最好不过. 新开个 webpack 插件/工具介绍的文章系列,约莫每周更新一篇篇幅适中的文章聊以共勉, ...

  4. javascript中的构造函数和继承

    1.第一节 使用工厂模式创建一个构造函数CreatePerson function CreatePerson(name,sex){//构造函数:用于构造对象 可以说在js里类就是构造函数 //1.原料 ...

  5. 数据结构之数据的next和nextval

    KMP算法是模式匹配专用算法. 它是在已知模式串的next或nextval数组的基础上执行的.如果不知道它们二者之一,就没法使用KMP算法,因此我们需要计算它们. KMP算法由两部分组成: 第一部分, ...

  6. 学习php语法--数据库扩展(总结篇)

      前  言  php  php中的数据库扩展mysql语法--本篇学习都是通过使用数字天堂的HBuider开发环境,连接mysql数据.介绍php连接mysql数据库的代码与函数. 本篇学习主要有两 ...

  7. java设计模式综合项目实战视频教程

    java设计模式综合项目实战视频教程 视频课程目录如下: 第01节课:本课程整体内容介绍:X-gen系统概况,包括:引入.X-gen项目背景.X-gen的HelloWorld第02节课:X-gen整体 ...

  8. linux下安装apache最常见的报错解决

    报错如下: Starting httpd: httpd: Could not reliably determine the server's fully qualified domain name, ...

  9. IOS 固定定位底部input输入框,获取焦点时弹出的输入法键盘挡住input

    移动页面经常会做到这样一个效果,看下面的图片,重点就是那个固定定位的底部,里面有个input输入框,在输入字符的时候,安卓手机看着是完全没有问题! 1.页面没有点击底部input的初始状态 2.安卓手 ...

  10. 【Android Developers Training】 82. 序言:传输数据时减少对电池寿命的影响

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...