MyBatis四映射器

来源:互联网 发布:mac上最好的绘画软件 编辑:程序博客网 时间:2024/05/20 20:22
映射器,是MyBatis最强大的工具,也是我们使用MyBatis用的最多的工具,因此熟练掌握它十分必要。MyBatis是针对映射器构造的SQL构建的轻量级框架,
并且通过配置生成对应的JavaBean返回给调用者,而这些配置主要便是映射器。
一、映射器元素
select 查询语句
insert 插入语句
update 更新语句
delete 删除语句
parameterMap 定义参数的映射关系
sql 允许定义一部分SQL然后在各个地方引用,如whereSQL
resultMap 用来描述从数据库结果集中来加载对象,它是最复杂、最强大的元素
cache 给定命名空间的缓存配置
cache-ref 其他命名空间缓存配置的引用


select 元素
id、parameterType(参数)、resultType(返回的结果类型不能与resultMap同时使用)、resultMap(强大的映射集的引用)、flushCache(是否清除二级缓存和本地缓存)、
useCache(是否开启二级缓存)、databaseId(数据库厂商)、
自动映射:
参数autoMappingBehavior,当它不为空的NONE的时候,MyBatis会提供自动映射的功能,只要返回的SQL列名和JavaBean的属性名是一样的就行,
实际情况下我们使用别名的机制或者配置mapUnderscoreToCamelCase为true,就可以实现自动映射的功能。
多个参数:
1、使用map传递参数
 <select id='id' parmeterType="map" resultMap="roleMap">
select * from T_role where id=#{roleName}
 </select>
 public List<Role> findRoleByMap(<Map<String,String> params);
2、使用注解
public List<Role> findRoleBy(@Param("roleName") String roleName,@Param("note") String note);
 <select id='id' resultMap="roleMap">
select * from T_role where id=#{roleName} and note=#{note}
 </select>
3、使用JavaBean传递参数
  <select id='id' parmeterType="com.beans.bean" resultMap="roleMap">
select * from T_role where id=#{roleName} and note=#{note}
 </select>
  public List<Role> findRoleByParams(Bean bean)
  
resultMap:
在处理复杂的映射的时候,使用resultMap,我们需要在映射器中定义resultMap
<resultMap id="roleResultMap" type="come.bean.Role">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="note" column="note"/>
</resultMap>


<select parameterType="long" id="getRole" resultMap="roleResultMap">
select id,role_name,note from t_role where id=#{id}
</select>


insert元素,myBatis会在执行插入之后返回一个整数,表示执行操作后插入的记录数
id、parameterType(参数)、flushCache(是否清除缓存)、keyProperty(表示哪个列作为属性的主键,不能和keyColumn同时使用)、
useGeneratedKeys(使MyBatis使用JDBC的getGeneratedKeys方法来取出由数据库内部生产的主键,使用了它就必须给keyColumn或者可以keyProperty赋值)、
keyColumn(指明第几列,用整形)、databaseId(指定数据库厂商)


<insert parameterType="role" id="insertRole" useGeneratedKeys="true" keyProperty="id">
insert into t_role(role_name,note) values(#{roleName},#{note})
</insert>


自动增长的不适用的情况下,可能要指定增长规则,则使用selectKey
selectKey:
<insert parameterType="role" id="insertRole" useGeneratedKeys="true" keyProperty="id">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select if(max(id) is null,1,max(id)+2) as newId from t_role
</selectKey>
insert into t_role(id,role_name,note) values(#{id},#{roleName},#{note})
</insert>
order 有BEFORE和AFTER,根据不同数据库生成主键的机制取不同值,
1:BEFORE,会先选择主键,然后设置keyProperty,再执行insert语句;
2:AFTER,就先运行insert 语句再运行selectKey 语句。
在Oracle经常使用序列、在MySQL中使用函数来自动生成插入表的主键


update和delete,返回一个整数,表示执行后影响的条数
<update parameterType="role" id="updateRole">
update t_role set
role_name=#{role_name},
note=#{note}
where id=#{id}
</update>


<delete parameterType="long" id="delete">
delete from T_role where id=#{id}
</delete>


参数:
我们可以通过指定参数的类型去让对应的typeHandler处理它们,定义参数属性的时候,MyBatis不允许换行。
#{age,javaType=int,jdbcType=NUMERIC}
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
#{age,javaType=int,jdbcType=NUMERIC,numericScale=2}//设置保存的精度


存储过程:
对于存储过程而言,存在三种参数,IN、OUT、INOUT,MyBatis的参数规则为其提供了良好的支持,我们通过制定mode属性来确定其是哪一种参数。当参数为OUT或者为INOUT的时候,
MyBatis会将存储过程返回的结果设置到你制定的参数中。当你返回的是一个游标(JdbcType=CURSOR)的时候,你还需要去设置resultMap以便MyBatis将存储过程的参数映射到对
应的类型,这时候MyBatis就会通过你所设置的resultMap自动为你设置映射结果。
#{role,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=myResultMap}//javaType可选,MyBatis会自动检测它
同时,MyBatis还支持结构体,需要指定语句类型的名称(jdbcTypeName=my_type这样)
主要,当字段返回值可能是空null的时候,我们需要去指定字段类型,因为null值MyBatis无法判断其类型。
#{roleNo},#{roleName},#{note,jdbcType=VARCHAR}


特殊字符串替换和处理(#和$)
在MyBatis中我们经常传递字符串,我们设置的的参数#{name}在大部分情况下MyBatis会用创建预编译的语句,然后MyBatis为它设值,然而我们有时候需要的是
传递SQL本身而不是SQL所需要的参数,如动态列的时候,我们需要用程序传递数据列,每次查询的列可能不同,此时我们不希望MyBatis去转译这些参数,
就用${},就不会使用预编译
select ${columns} from t_tablename where role_id=#{roleId}


这样MyBatis就不会帮我们转译column了,而变为直出,预编译为以下内容。
seelct table_name from t_talename where role_id=?


sql元素:我们可以定义一串SQL语句的组成部分,其他的语句可以通过引用来使用它


<sql id="pageBeginSql">
  select * from (select tz.*, rownum row_num 
from (
</sql>


<sql id="pageEndSql">
  ) tz  where rownum &lt;= #{endNum}) where row_num &gt;= #{beginNum}
</sql>
<select>
<include refid="pageBeginSql">
select * from t_role
<include refid="pageEndSql">
<select>


resultMap:
它的作用是定制映射规则、级联的更新、定制类型装换器等。MyBatis现有的版本只支持resultMap查询,不支持更新或者保存,
更不必说级联的更新、删除和修改了。
<resultMap>
<constructor>
<idArg/>
<arg>
</constructor>
<id/>
<result/>
<association/>
<collection/>
<descriminator>
<case/>
</descriminator>
</resultMap>
其中constructor元素用于配置构造方法,一个POJO可能不存在没有参数的构造方法,这个时候我们就是用constructor进行配置。
<resultMap ......>
<constructor>
<idArg column="id" >
<arg column="role_name" javaType="string">
</constructor>
......
</resultMap>


存储结果集
一、map
一般而言,任何的select语句都可以使用map存储。
<select id="findColorByNote" parameterType="string" resultType="map">
select * from t_role where 1=1 and note like concat('%',#{note},'%')
</select>
二、使用POJO存储结果
<resultMap id="roleMap" type="com.kang.Role">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
</resultMap>
<select parameterType="long" id="getRole" resultMap="roleMap">
select * from t_role where id=#{id}
</select>


级联
association 一对一
<mapper namespace="com.kang.studentSelfcardMapper" >
<resultMap type="com.kang.StudentSelfcardBean" id="studentSelfcardMap">
<id property="id" column="id">
<result property="studentId" column="student_id"/>
<result property="SelfName" column="self_name"/>
<select id="findStudentSelfcardByStudentId" paramterType="int" resultMap="studentSelfcardMap">
select * from t_role where id=#{id}
</select>
</resultMap>
<mapper>


<mapper namespace="com.kang.studentMapper" >
<resultMap type="com.kang.StudentBean" id="studentMap">
<id property="id" column="id">
<result property="studentId" column="student_id"/>
<result property="studentName" column="student_name"/>
<association property="studentSelfcard" column='id' select="com.kang.studentSelfcardMapper.findStudentSelfcardByStudentId"></association>
<select id="getStudent" paramterType="int" resultMap="studentMap">
select * from t_role where id=#{id}
</select>
</resultMap>
<mapper>
column='id'是传递的参数,可以多个,用“,”号隔开
 
collection 一对多
<mapper namespace="com.kang.studentMapper" >
<resultMap type="com.kang.StudentBean" id="studentMap">
<id property="id" column="id">
<result property="studentId" column="student_id"/>
<result property="studentName" column="student_name"/>
<collection property="studentLectureList" column='id' select="com.kang.studentLectureMapper.getStudentLectureByStuId"></collection>


</resultMap>
<select id="getStudent" paramterType="int" resultMap="studentMap">
select * from t_role where id=#{id}
</select>
<mapper>


<mapper namespace="com.kang.studentLectureMapper" >
<resultMap type="com.kang.StudentLectureBean" id="studentLectureMap">
<id property="id" column="id">
<result property="studentId" column="student_id"/>
<result property="grade" column="grade"/>
</resultMap>
<select id="getStudentLectureByStuId" paramterType="int" resultMap="studentLectureMap">
select * from t_lecture where stu_id=#{id}
</select>
<mapper>
discriminator 鉴别器,可以根据实际选择采用哪个类作为实例,允许你根据特定的条件去关联不同的结果集


性能分析和N+1问题
级联就会出现著名的N+1问题了,和其他ORM框架一样MyBatis也有延迟加载的功能,两个全局参数lazyLoadingEnable和aggressiveLazyLoading
lazyLoadingEnable:是否开启延迟加载功能
<settings>
<setting name="lazyLoadingEnable" value="true"></setting>
</settings>
也可以在association和collection中使用fetchType="lazy"、"eager"来设置
aggressiveLazyLoading是否按层级加载,MyBatis默认情况下是使用层级加载策略,即同一级的延迟数据只要加载其中一个,其余就会全部加载出来,
此时用aggressiveLazyLoading = false 就是按需加载。延迟加载的原理是动态代理。


缓存:
缓存就是把数据保存在计算机的内存上,读取的时候无需在从磁盘读入,因此具备快速读取和使用的特点,如果缓存命中率高,可以极大的提高系统的性能。
使用缓存的关键在于存储内容访问的命中率。目前流行的缓存服务器有MongoDB、Redis、Ehcache等。
一级缓存:MyBatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于SqlSession而言,各个SqlSession是相互隔离的;
二级缓存:SqlSessionFactory层面的二级缓存是不开启的,二级缓存需要配置<cache/>元素,MyBatis要求返回的POJO是可序列化的,
也就是实现Serializable接口。
<cache eviction="LRU" flushInterval="100000" size="1024" readOnly=true"/>
eviction:缓存回收策略
flushInterva:刷新间隔时间
size:引用数目
readyOnly:只读,意味着缓存数据只能读取不能修改


自定义缓存:
在大型服务器上,会使用各类不同的缓存服务器,这个时候我们可以定制缓存,比如现在流行的redis缓存,我们需要实现,org.apache.ibatis.cache.Cache
根据不同的缓存做不同的实现,做完实现后,再配置
<cache type="com.kang.MyCache">
<property name="host" value="localhost"/> <!--可以配置一些缓存中常用的属性 -->
</cache>
在MyCache增加setHost方法,初始化的时候,会被调用到,这样就可以对自定义设置一些外部参数
我们也可以配置SQL层面的缓存机制,来决定它们是否需要使用或者刷新缓存,根据useCache和flushCache两个属性来完成,useCache标志是否使用,
flushCache标志插入后是否需要刷新
0 0
原创粉丝点击