1.搭建Mybatis环境简述
1)创建实体类UserEntity
2)创建数据访问接口UserMapper
3)创建SQL映射语句文件UserMapper.xml
4)创建Mybatis的mapper配置文件mybatis-config.xml
5)修改Spring的配置文件
2.SQL语句映射文件-resultMap
1)SQL映射XML文件,是所有SQL语句放置的地方。
2)SQL映射XML文件一些初级的元素:
cache - 配置给定模式的缓存
cache-ref - 从别的模式中引用一个缓存
resultMap - 最复杂且最强大的一个元素,它描述如何从结果集中加载对象
sql - 一个可以被其他语句复用的SQL块
insert - 映射insert语句
update - 映射update语句
delete - 映射delete语句
select - 映射select语句
3)resultMap的属性:
type 为java实体类
id 为此resultMap的标识
4)resultMap可以设置的映射:
4.1)id, result
id、result是最简单的映射,id为主键映射; result其他基本数据库表字段到实体类属性的映射。
配置细节:
property 需要映射到JavaBean的属性名称
column 数据表的列名或者标签别名
javaType 一个完整的类名,或者是一个类型别名
jdbcType 数据表支持的类型列表 (这个属性只在insert,update或delete 的时候针对允许空的列有用)
支持的JDBC类型:
bit, float, char, timestamp, other, undefined, tinyint, real, varchar, binary, blob, nvarchar, smallint, double
typeHandler 使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名.
4.2)constructor
我们使用id、result时候,需要定义java实体类的属性映射到数据库表的字段上,这个时候是使用JavaBean实现的。
当然我们也可以使用实体类的构造方法来实现值的映射,这个时候是通过构造方法参数的书写的顺序来进行赋值的。
使用construcotr功能有限(例如使用collection级联查询)。
把映射文件改写为:
<resultMap type="StudentEntity" id="studentResultMap" >
<constructor>
<idArg javaType="String" column="STUDENT_ID"/>
<arg javaType="String" column="STUDENT_NAME"/>
<arg javaType="String" column="STUDENT_SEX"/>
<arg javaType="Date" column="STUDENT_BIRTHDAY"/>
</constructor>
</resultMap>
实体类构造方法:
public StudentEntity(String studentID, String studentName, String studentSex, Date studentBirthday){
this.studentID = studentID;
this.studentName = studentName;
this.studentSex = studentSex;
this.studentBirthday = studentBirthday;
}
4.3)association联合
association用来处理一对一的关系
需要指定映射的Java实体类的属性,属性的javaType(通常MyBatis自己会识别),对应的数据库表的列名称
如果想覆写返回结果的值,需要制定typeHandler
MyBatis可以用两种方式加载:
4.3.1)select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活;
ClassMapper.xml
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" select="getTeacher"/>
</resultMap>
<select id="getClassByID" parameterType="String" resultMap="classResultMap">
SELECT * FROM CLASS_TBL CT
WHERE CT.CLASS_ID = #{classID};
</select>
TeacherMapper.xml
<resultMap type="TeacherEntity" id="teacherResultMap">
<id property="teacherID" column="TEACHER_ID" />
<result property="teacherName" column="TEACHER_NAME" />
<result property="teacherSex" column="TEACHER_SEX" />
<result property="teacherBirthday" column="TEACHER_BIRTHDAY"/>
<result property="workDate" column="WORK_DATE"/>
<result property="professional" column="PROFESSIONAL"/>
</resultMap>
<select id="getTeacher" parameterType="String" resultMap="teacherResultMap">
SELECT *
FROM TEACHER_TBL TT
WHERE TT.TEACHER_ID = #{teacherID}
</select>
4.3.2)resultsMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" resultMap="teacherResultMap"/>
</resultMap>
<select id="getClassAndTeacher" parameterType="String" resultMap="classResultMap">
SELECT *
FROM CLASS_TBL CT LEFT JOIN TEACHER_TBL TT ON CT.TEACHER_ID = TT.TEACHER_ID
WHERE CT.CLASS_ID = #{classID};
</select>
4.4)collection聚集
collection用来处理一对多的关系
需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList),列表中对象的类型ofType(Java实体类),对应的数据库表的列名称
4.4.1)select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活;
ClassMapper.xml
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" select="getTeacher"/>
<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" select="getStudentByClassID"/>
</resultMap>
<select id="getClassByID" parameterType="String" resultMap="classResultMap">
SELECT * FROM CLASS_TBL CT
WHERE CT.CLASS_ID = #{classID};
</select>
StudentMapper.xml
<resultMap type="StudentEntity" id="studentResultMap">
<id property="studentID" column="STUDENT_ID" />
<result property="studentName" column="STUDENT_NAME" />
<result property="studentSex" column="STUDENT_SEX" />
<result property="studentBirthday" column="STUDENT_BIRTHDAY" />
</resultMap>
<select id="getStudentByClassID" parameterType="String" resultMap="studentResultMap">
<include refid="selectStudentAll" />
WHERE ST.CLASS_ID = #{classID}
</select>
4.4.2)使用resultMap实现聚集
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" resultMap="teacherResultMap"/>
<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" resultMap="studentResultMap"/>
</resultMap>
<select id="getClassAndTeacherStudent" parameterType="String" resultMap="classResultMap">
SELECT *
FROM CLASS_TBL CT
LEFT JOIN STUDENT_TBL ST
ON CT.CLASS_ID = ST.CLASS_ID
LEFT JOIN TEACHER_TBL TT
ON CT.TEACHER_ID = TT.TEACHER_ID
WHERE CT.CLASS_ID = #{classID};
</select>
4.5)discriminator鉴别器
有时一个单独的数据库查询也许返回很多不同数据类型的结果集(但是希望有些关联)
discriminator元素就是被设计来处理这个情况的,还有包括类的继承层次结构
discriminator非常容易理解,因为它的表现很像Java语言中的switch语句
定义鉴别器指定了column和javaType属性
column是MyBatis查找比较值的地方
JavaType是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)
下面这个例子为,当classId为20000001时,才映射classId属性
<resultMap type="liming.student.manager.data.model.StudentEntity" id="resultMap_studentEntity_discriminator">
<id property="studentId" column="STUDENT_ID" javaType="String" jdbcType="VARCHAR"/>
<result property="studentName" column="STUDENT_NAME" javaType="String" jdbcType="VARCHAR"/>
<result property="studentSex" column="STUDENT_SEX" javaType="int" jdbcType="INTEGER"/>
<result property="studentBirthday" column="STUDENT_BIRTHDAY" javaType="Date" jdbcType="DATE"/>
<result property="studentPhoto" column="STUDENT_PHOTO" javaType="byte[]" jdbcType="BLOB" typeHandler="org.apache.ibatis.type.BlobTypeHandler" />
<result property="placeId" column="PLACE_ID" javaType="String" jdbcType="VARCHAR"/>
<discriminator column="CLASS_ID" javaType="String" jdbcType="VARCHAR">
<case value="20000001" resultType="liming.student.manager.data.model.StudentEntity" >
<result property="classId" column="CLASS_ID" javaType="String" jdbcType="VARCHAR"/>
</case>
</discriminator>
</resultMap>
3.SQL语句映射文件-增删改查、参数、缓存
3.1)select
<select id="getStudent" parameterType="String" resultMap="studentResultMap">
SELECT ST.STUDENT_ID,
ST.STUDENT_NAME,
ST.STUDENT_SEX,
ST.STUDENT_BIRTHDAY,
ST.CLASS_ID
FROM STUDENT_TBL ST
WHERE ST.STUDENT_ID = #{studentID}
</select>
select语句属性配置细节:
id 在这个模式下唯一的标识符,可被其它语句引用
parameterType 传给此语句的参数的完整类名或别名
resultType 语句返回值类型的整类名或别名 (resultType 与resultMap 不能并用)
resultMap 引用的外部resultMap名,结果集映射是MyBatis 中最强大的特性
flushCache 如果设为true,则会在每次语句调用的时候就会清空缓存。 select语句默认设为false
useCache 如果设为true,则语句的结果集将被缓存。select 语句默认设为false
timeout 设置驱动器在抛出异常前等待回应的最长时间,默认为不设值,由驱动器自己决定
fetchSize 设置一个值后,驱动器会在结果集数目达到此数值后,激发返回,默认为不设值,由驱动器自己决定
statementType statement, prepared(预准备语句), callable(可调用语句)
resultSetType forward_only(只转发), scroll_sensitive(滚动敏感), scroll_insensitive(不区分大小写的滚动)
3.2)insert
3.3)update/delete
3.4)sql
3.5)parameters
MyBatis可以使用的基本数据类型和Java的复杂数据类型。
基本数据类型,String,int,date等。
但是使用基本数据类型,只能提供一个参数,所以需要使用Java实体类,或Map类型做参数类型。
通过#{}可以直接得到其属性。
3.5.1)基本类型参数
<!-- 查询学生list,根据入学时间 -->
<select id="getStudentListByDate" parameterType="Date" resultMap="studentResultMap">
SELECT *
FROM STUDENT_TBL ST LEFT JOIN CLASS_TBL CT ON ST.CLASS_ID = CT.CLASS_ID
WHERE CT.CLASS_YEAR = #{classYear};
</select>
3.5.2)Java实体类型参数
3.5.3)Map参数
3.5.4)多参数的实现
3.5.5)字符串代入法
3.6)cache缓存
3.6.1)MyBatis 包含一个强在的、可配置、可定制的缓存机制。
MyBatis 3 的缓存实现有了许多改进,既强劲也更容易配置。
默认的情况,缓存是没有开启,除了会话缓存以外,它可以提高性能,且能解决全局依赖。
3.6.2)开启二级缓存,你只需要在SQL 映射文件中加入简单的一行:<cache/>
这句简单的语句的作用如下:
1. 所有在映射文件里的select 语句都将被缓存。
2. 所有在映射文件里insert,update 和delete 语句会清空缓存。
3. 缓存使用“最近很少使用”算法来回收
4. 缓存不会被设定的时间所清空。
5. 每个缓存可以存储1024 个列表或对象的引用(不管查询出来的结果是什么)。
6. 缓存将作为“读/写”缓存,意味着获取的对象不是共享的且对调用者是安全的。不会有其它的调用,者或线程潜在修改。
3.6.3)例如,创建一个FIFO 缓存让60 秒就清空一次,存储512 个对象结果或列表引用,并且返回的结果是只读。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"></cache>
因为在不用的线程里的两个调用者修改它们可能会导致引用冲突。
还可以在不同的命名空间里共享同一个缓存配置或者实例。在这种情况下,你就可以使用cache-ref 来引用另外一个缓存。
<cache-ref namespace="com.liming.manager.data.StudentMapper"/>
3.6.4)Cache 语句属性配置细节:
eviction:
缓存策略(默认值LRU)
LRU - 最近最少使用法:移出最近较长周期内都没有被使用的对象。
FIFI- 先进先出:移出队列里较早的对象
SOFT - 软引用:基于软引用规则,使用垃圾回收机制来移出对象
WEAK - 弱引用:基于弱引用规则,使用垃圾回收机制来强制性地移出对象
flushInterval:(默认不设置)
代表一个合理的毫秒总计时间。默认是不设置,因此使用无间隔清空即只能调用语句来清空。
size:(默认1024)
缓存的对象的大小
readOnly:(默认是false)
只读缓存将对所有调用者返回同一个实例。
因此都不能被修改,这可以极大的提高性能。
可写的缓存将通过序列化来返回一个缓存对象的拷贝。
这会比较慢,但是比较安全。所以默认值是false。