MyBatis小试
Spring MyBatis小试
之前了解过Hibernate,感觉不写SQL语句好爽啊。后来写了一个小程序用来计算东西,用Hibernate,但是War包实在是太大了,想要减小下体积,于是试了试MyBatis,感觉不错。写下来方便以后使用。主要是参考了MyBatis官方的文章MyBatis和MyBatis-Spring。
搭建环境
IDE用的Intellij IDEA,数据库用的H2 Database,包管理Gradle,日志Log4j,然后MyBatis,数据用的是Oracle数据库自带的测试数据UTLSAMPLE.sql。其中build.gradle如下。
1 | apply plugin: 'java' |
配置Spring和MyBatis
参照官方文档,建立配置文件JdbcConfig.java
。
1 |
|
ORM Model类配置
根据测试数据的结构,主要使用了EMP和DEPT两个表,就设置两个Model类Employee
与Department
。
1 | public class Department implements Serializable { |
1 | public class Employee implements Serializable { |
配置Mapper
创建Mapper接口类,SQL语句可以使用Annotation或XML文件。其实我一直蛮喜欢用Annotation来配置的,比如Spring,但是MyBatis用Annotation来配置SQL语句的话,使用代码特别长,不好看,就改用XML方式了。
1 | public interface UtliMapper { |
嵌入Select查询
在处理上面查询一个Employy
的时候,属性包含Employee mgr
和Department deparment
,数据库里面是ID。mgr里面还有mgr,一直这样下去,而Department里面又有List<Employee>
,如果查询方式为Eager
的话,就会一次查询导致在数据库N多次查询。刚开始感觉还是Hibernate的简单,配置@ManyToOne
和@OneToMany
基本就解决了。MyBatis就自己写吧,哈哈。这里有个坑,就是配置ResultMap的时候,association和collection时,需要放最后。我理解的话就是,assocation对应XxxToOne
,collection对应OneToXxx
。
1 | <mapper namespace="com.liangwu.mybatis.model.mapper.UtliMapper"> |
嵌入Select结果
还有一种是直接写好SQL语句,一次查询完结果返回,这样对于复杂的结构性能上应该会好一些,毕竟查询一次只用跟数据库打一次交道,而上一个方法一次查询可能需要跟数据库交流好几次。这个就是按业务要求拼SQL语句了。
1 | <resultMap id="dept" type="Department"> |
测试
用Junit来单元测试吧。这样就应该可以看到结果咯。
1 |
|
FetchType中Eager和Lazy的小区别
下面是分别在Select嵌入查询时使用Eager和Lazy的区别。可以看到Eager的时候,是SQL里再嵌套;而Lazy的时候,是分别查询。这样在分析业务和调优的时候可以针对性使用了。
1 | DEBUG [main] - ==> Preparing: SELECT * FROM dept WHERE deptno=? |
1 | DEBUG [main] - ==> Preparing: SELECT * FROM dept WHERE deptno=? |
嵌入Select查询和嵌入Select结果的区别
其实这个通过配置Mapper的时候就可以看出来了,一个是通过几次查询,一个是通过一次查询来解决问题的。测试了下mapper.selectEmpById(7782)
,看看结果有什么不一样。
1 | DEBUG [main] - ==> Preparing: SELECT * FROM emp e WHERE e.empno=? |
1 | DEBUG [main] - ==> Preparing: SELECT e.empno, e.ename, e.job, e.hiredate, e.sal, e.comm, d.deptno, d.dname, d.loc, e2.empno as mgr_empno, e2.ename as mgr_ename, e2.job as mgr_job, e2.hiredate as mgr_hiredate, e2.sal as mgr_sal, e2.comm as mgr_sal, e2.deptno as mgr_deptno FROM emp e LEFT OUTER JOIN dept d on e.deptno=d.deptno LEFT OUTER JOIN emp e2 on e.mgr=e2.empno WHERE e.empno=? |
其它
之前在看MyBatis的时候,有时候需要自己配置其它的SQL语句,比如用Map来进行动态查询,Key值表示查询的列,Value表示查询值。select * from emp where ${key}=#{value}
,注意到$和#的区别,$的参数直接输出,#的参数会被替换为?,然后传入参数值执行。通过看Log文件大概就知道,一个是在生成SQL语句的时候就把${}替换(替换后SQL语句就生成了),另一个是在查询的时候把#{}代入?当中。