你的位置:首页 > 软件开发 > Java > 再学习之MyBatis

再学习之MyBatis

发布时间:2017-11-13 13:00:41
一、框架基本介绍1、概念支持普通SQL查询、存储过程和高级映射,简化和实现了Java 数据持久化层的的开源框架,主要流行的原因在于他的简单性和易使用性。2、特点持久层 、ORM(对象关系映射) 、轻量级、支持SQL语句。3、工作原理应用程序读取mybatis的配置文件,形成配置对 ...

一、框架基本介绍

1、概念

支持普通SQL查询、存储过程和高级映射,简化和实现了Java 数据持久化层的的开源框架,主要流行的原因在于他的简单性和易使用性。

2、特点

持久层 、ORM(对象关系映射) 、轻量级、支持SQL语句。

3、工作原理

  • 应用程序读取mybatis的配置文件,形成配置对象。
  • 通过sqlsessionfactorybuilder读取配置对象,产生sqlsessionfactory
  • 通过sqlsessionfactory得到sqlsession
  • 通过sqlsession得到mapper映射器
  • 通过mapper读取对应的映射文件从而操作数据库
  • 处理事务
  • 释放sqlsession

二、配置文件含义

1、environment   

再学习之MyBatis再学习之MyBatis
 <environments default="development">  <environment id="development">   <transactionManager type="JDBC" />   <dataSource type="POOLED">    <property name="driver" value="com.mysql.jdbc.Driver" />    <property name="url" value="jdbc:mysql://localhost:3306/test" />    <property name="username" value="root" />    <property name="password" value="admin" />   </dataSource>  </environment>  <environment id="test">   <transactionManager type="JDBC"></transactionManager>   <dataSource type="JNDI">    <property name="driver" value="com.mysql.jdbc.Driver" />    <property name="url" value="jdbc:mysql://localhost:3306/test" />    <property name="username" value="root" />    <property name="password" value="admin" />   </dataSource>  </environment> </environments>
View Code

 主要用来配置多个dataSource环境;在同一个环境中切换不同的dataSource时,需要为每个数据库创建一个SqlSessionFactory。对于每个环境 environment,我们需要配置 dataSource 和 transactionManager。

1.1 DateSource
  • UNPOOLED:为每一个数据库操作创建一个新的连接,使用结束就关闭他。该方式适用于小规模数量的并发用户的简单应用程序上。
  • POOLED:Mybatis会创建一个数据库连接池,连接池中的一个连接将会被用作数据库操作。一旦数据库操作完成,MyBatis 会将此连接返回给连接池。
  • JNDI:MyBatis 从在应用服务器向配置好的 JNDI 数据源 dataSource 获取数据库连接。
1.2 TransactionManager
  • JDBC:应用程序自己管理事务(Tomcat)
  • MANAGED:应用本身不去管理事务,而把事务管理交给应用所在的服务器进行管理。(JBoss、WebLogic、GlassFish)

2、properties

再学习之MyBatis再学习之MyBatis
<properties resource="application.properties"><property name="jdbc.username" value="db_user" /><property name="jdbc.password" value="verysecurepwd" /></properties>
View Code

这里,如果 application.properties 文件包含值 jdbc.username 和 jdbc.password,则上述定义的 username 和password 的值 db_user 和 verysecurepwd 将会被 application.properties 中定义的对应的 jdbc.username 和jdbc.password 值覆盖。

3、typeAliases

如果没有设置typeAliases的类型别名,对于resultType和parameterType属性值,我们需要使用JavaBean的完全限定名。所以,我们可以为完全限定名使用别名,通过typeAliases设置:

3.1 为每个JavaBean单独起别名
再学习之MyBatis再学习之MyBatis
<typeAliases><typeAlias alias="Student" type="com.mybatis3.domain.Student" /><typeAlias alias="Tutor" type="com.mybatis3.domain.Tutor" /></typeAliases>
View Code
3.2 为JavaBean 所在的包起别名

当然也可以不用为每一个JavaBean 单独定义别名,你可以为提供需要起别名的JavaBean 所在的包,Mybatis会自动扫描包内定义的JavaBeans,然后分别为JavaBean注册一个小写字母开头的非完全限定的类名形式的别名。

再学习之MyBatis再学习之MyBatis
<typeAliases><package name="com.mybatis3.domain" /></typeAliases>
View Code

如果 Student.java 和 Tutor.java 的 Bean 定义在 com.mybatis3.domain 包中,则 com.mybatis3.domain.Student的别名会被注册为 student。而 com.mybatis3.domain.Tutor 别名将会被注册为 tutor。

 3.3 利用注解的方式起别名

使用注解@Alias起别名,@Alias 注解将会覆盖配置文件中的<typeAliases>定义:

再学习之MyBatis再学习之MyBatis
@Alias("StudentAlias")public class Student{ }
View Code

4、typeHandlers

MyBatis 对于以下的类型使用内建的类型处理器:所有的基本数据类型、基本类型的包装类型、 byte[]、java.util.Date、 java.sql.Date、 java,sql.Time、 java.sql.Timestamp、 java 枚举类型等。所以当 MyBatis 发现属性的类型属于上述类型,他会使用对应的类型处理器将值设置到PreparedStatement 中,同样地,当从 SQL 结果集构建 JavaBean 时,也有类似的过程。

如果,我们可以自定义一个类型处理器为我们子定义的Class服务。一旦我们实现了自定义的类型处理器,我们需要在 mybatis-config.中注册它:

再学习之MyBatis再学习之MyBatis
 */public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber> { public void setNonNullParameter(PreparedStatement preparedStatement, int i, PhoneNumber phoneNumber, JdbcType jdbcType) throws SQLException {  preparedStatement.setString(i, phoneNumber.toString()); } public PhoneNumber getNullableResult(ResultSet resultSet, String s) throws SQLException {  return new PhoneNumber(resultSet.getString(s)); } public PhoneNumber getNullableResult(ResultSet resultSet, int i) throws SQLException {  return new PhoneNumber(resultSet.getString(i)); } public PhoneNumber getNullableResult(CallableStatement callableStatement, int i) throws SQLException {  return new PhoneNumber(callableStatement.getString(i)); } }
自定义类型处理器 再学习之MyBatis再学习之MyBatis
 <typeHandlers>  <typeHandler handler="com.summersoft.ts.util.PhoneTypeHandler"/> </typeHandlers>
注册自定义类型处理器

 时间类型:Mybatis 会将java.util.Data 类型转换成java.sql.Timestamp(时间戳)并设置。

5、Mappers

再学习之MyBatis再学习之MyBatis
<mappers> <mapper resource="com/mybatis3/mappers/StudentMapper. /> <mapper url="file:///D:/mybatisdemo/app/mappers/TutorMapper. /> <mapper class="com.mybatis3.mappers.TutorMapper" /> <package name="com.mybatis3.mappers" /></mappers>
View Code
  • resource 属性用来指定在 classpath 中的 mapper 文件。
  • url 属性用来通过完全文件系统路径或者 web URL 地址来指向 mapper 文件
  • class 属性用来指向一个 mapper 接口
  • package 属性用来指向可以找到 Mapper 接口的包名

三、映射文件讲解

  我们通过映射器配置文件配置了映射语句,同时创建一个完全对应的一个映射器接口。接口名跟配置文件名相同。接口所在包名也跟配置文件所在包名完全一 样。在配置文件中,其命名空间namespace 应该和接口的完全限定名保持一致。

1、INSERT

id: 对应接口的方法名
parameterType: 输入参数
useGeneratedKeys="true" :让数据库生成自增长的列
keyProperty="属性名": 将生成的值设置到其中一个输入对象属性内

如果是Oracle数据库,没有像MySQL那样的自增机制:

再学习之MyBatis再学习之MyBatis
 <insert id="insertStudent" parameterType="Student">  <selectKey keyProperty="studId" resultType="int" order="BEFORE">   SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL  </selectKey>  INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)  VALUES(#{studId},#{name},#{email},#{phone}) </insert>
View Code

order="BEFORE" 表示在插入语句发生前产生studId的值就赋给插入语句。

再学习之MyBatis再学习之MyBatis
 <insert id="insertStudent" parameterType="Student">  INSERT INTO STUDENTS(NAME,EMAIL, PHONE)  VALUES(#{name},#{email},#{phone})  <selectKey keyProperty="studId" resultType="int" order="AFTER">   SELECT ELEARNING.STUD_ID_SEQ.CURRVAL FROM DUAL  </selectKey> </insert>
View Code

 order="AFTER" 表示在插入语句之后采用触发器(trigger)来设置主键值

2、SELECT

2.1、 resultType='Student' 当 column名和对象property名一致时,会自动把相应的column填充上对象的property,如果查询记录返回多条,Mybatis 自动用 集合类来接收。

2.2、Mybatis根据集合的类型,会采用适当的集合实现:

对于 List,Collection,Iterable 类型,MyBatis 将返回 java.util.ArrayList
对于 Map 类型,MyBatis 将返回 java.util.HashMap
对于 Set 类型,MyBatis 将返回 java.util.HashSet
对于 SortedSet 类型,MyBatis 将返回 java.util.TreeSet

2.3、ResultType 和 ResuleMap 不能同时使用,ResultMap的 id 在此命名空间内是唯一的 

2.4、Resulttype="java.util.HashMap"。在这种情况下,结果集中的列名将会作为Map中的key值,而列值作值将会作为Map的value值。如果查询记录返回多条,Mybatis自动用集合类来接收。

2.5、我们可以从另外一个<resultMap>,扩展出一个新的<resultMap>,这样原来的属性值可以扩展过来

2.6、一对一关联查询

再学习之MyBatis再学习之MyBatis
 <resultMap type="Student" id="StudentWithAddressResult">  <id property="studId" column="stud_id" />  <result property="name" column="name" />  <result property="email" column="email" />  <result property="phone" column="phone" />  <result property="address.addrId" column="addr_id" />  <result property="address.street" column="street" />  <result property="address.city" column="city" />  <result property="address.state" column="state" />  <result property="address.zip" column="zip" />  <result property="address.country" column="country" /> </resultMap>
一对一直接关联再学习之MyBatis再学习之MyBatis
 <resultMap type="Address" id="AddressResult">  <id property="addrId" column="addr_id" />  <result property="street" column="street" />  <result property="city" column="city" />  <result property="state" column="state" />  <result property="zip" column="zip" />  <result property="country" column="country" /> </resultMap> <resultMap type="Student" id="StudentWithAddressResultIn">  <id property="studId" column="stud_id" />  <result property="name" column="name" />  <result property="email" column="email" />  <association property="address" resultMap="AddressResult" /> </resultMap>
一对一嵌套关联再学习之MyBatis再学习之MyBatis
 <resultMap type="Student" id="StudentWithAddressResultHasOne">  <id property="studId" column="stud_id" />  <result property="name" column="name" />  <result property="email" column="email" />  <association property="address" javaType="Address">   <id property="addrId" column="addr_id" />   <result property="street" column="street" />   <result property="city" column="city" />   <result property="state" column="state" />   <result property="zip" column="zip" />   <result property="country" column="country" />  </association> </resultMap>
一对一内联关联has one

2.7、一对多关联查询

再学习之MyBatis再学习之MyBatis
 <resultMap type="Course" id="CourseResult">  <id column="course_id" property="courseId" />  <result column="name" property="name" />  <result column="description" property="description" />  <result column="start_date" property="startDate" />  <result column="end_date" property="endDate" /> </resultMap> <resultMap type="Tutor" id="TutorResult">  <id column="tutor_id" property="tutorId" />  <result column="tutor_name" property="name" />  <result column="email" property="email" />  <collection property="courses" resultMap="CourseResult" /> </resultMap>
View Code

2.8、在MyBatis的配置文件中,可以不指定输入参数。而采用#{param1}和#{param2}引用接口中方法的形参。

 3、动态SQL

3.1 if 条件

再学习之MyBatis再学习之MyBatis
 <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">   SELECT * FROM COURSES   WHERE TUTOR_ID= #{tutorId}   <if test="courseName != null">    AND NAME LIKE #{courseName}   </if>   <if test="startDate != null">    AND START_DATE > #{startDate}   </if>   <if test="endDate != null">    AND END_DATE &lt; #{endDate}   </if>  </select>
if 语句

3.2 choose when条件

再学习之MyBatis再学习之MyBatis
 <select id="searchCoursesTwo" parameterType="hashmap" resultMap="CourseResult">  SELECT * FROM COURSES  <choose>   <when test="searchBy == 'Tutor'">    WHERE TUTOR_ID= #{tutorId}   </when>   <when test="searchBy == 'CourseName'">    WHERE name like #{courseName}   </when>   <otherwise>    WHERE TUTOR start_date >= now()   </otherwise>  </choose> </select>
choose when 条件

<choose>测试条件的值,且使用第一个值为TRUE的子句,如果没有条件为True,则使用<otherwise>内的字句

3.3 where 条件

再学习之MyBatis再学习之MyBatis
 <select id="searchCourses" parameterType="hashmap"   resultMap="CourseResult">  SELECT * FROM COURSES  <where>   <if test=" tutorId != null ">    TUTOR_ID= #{tutorId}   </if>   <if test="courseName != null">    AND name like #{courseName}   </if>   <if test="startDate != null">    AND start_date >= #{startDate}   </if>   <if test="endDate != null">    AND end_date &lt;= #{endDate}   </if>  </where> </select>
Where 子句

<where>元素只有在内部标签有返回内容时才会在动态语句上插入WHERE条件语句。并且,如果Where子句以AND 或者 OR 打头,则打头的AND 或 OR 将会被移除。

3.4 trim 条件

再学习之MyBatis再学习之MyBatis
 <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">  SELECT * FROM COURSES  <trim prefix="WHERE" prefixOverrides="AND | OR">   /*拼接成的字句前面加上WHERE,如果WHERE后面有AND 或者 OR,将去掉。suffix末尾加上,suffixOverrides 末尾去掉*/   <if test=" tutorId != null ">    TUTOR_ID= #{tutorId}   </if>   <if test="courseName != null">    AND name like #{courseName}   </if>  </trim> </select>
trim 子句

 <trim> 元素和 <where>元素类似,如果任意一个<if>条件为true,<trim>元素会插入WHERE,并且移除紧跟WHERE 后面的AND 或 OR

3.5 foreach 循环

再学习之MyBatis再学习之MyBatis
 <select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult">  SELECT * FROM COURSES  <if test="tutorIds != null">   <where>    <foreach item="tutorId" collection="tutorIds">     OR tutor_id=#{tutorId}    </foreach>   </where>  </if> </select>
foreach子句

它可以迭代遍历一个数组或者列表,构造AND/OR条件或者一个IN子句。

3.6 set 条件

再学习之MyBatis再学习之MyBatis
 <update id="updateStudent" parameterType="Student">  update students  <set>   <if test="name != null">name=#{name},</if>   <if test="email != null">email=#{email},</if>   <if test="phone != null">phone=#{phone},</if>  </set>  where stud_id=#{id} </update>
set子句

如果<if>条件返回了任何文本内容,<set>将会插入set关键字和其文本内容。并且会剔除末尾的","

 4、缓存

4.1、第一级缓存:如果你使用同一个SqlSession 接口对象调用了相同的SELECT语句,则直接会从缓存中返回结果,而不是再查询一次数据库。

4.2、第二级缓存:我们可以在SQL映射器

  • 所有的在映射语句文件定义的<select>语句的查询结果都会被缓存
  • 所有的在映射语句文件定义的<insert>,<update> 和<delete>语句将会刷新缓存
  • 缓存根据最近最少被使用(Least Recently Used,LRU)算法管理
  • 缓存不会被任何形式的基于时间表的刷新(没有刷新时间间隔),即不支持定时刷新机制
  • 缓存将存储 1024 个 查询方法返回的列表或者对象的引用
  • 缓存是线程安全的

当然我们也可以 复写默认属性来自定义缓存的行为:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

eviction:LRU、FIFO、SOFT、WEAK
readOnly:一个只读的缓存会向调用者返回被缓存对象的一份引用。一个读/写缓存cache将会返回改对象的一份拷贝。

 

 

 

原标题:再学习之MyBatis

关键词:mybatis

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录