MyBatis的核心配置文件配置了很多影响MyBatis行为的信息,这些信息通常只会配置在一个文件中,并且不会轻易改动。另外,与Spring框架整合后,MyBatis的核心配置文件信息将配置到Spring的配置文件中。因此,在实际开发中需要编写或修改MyBatis的核心配置文件的情况不多。
元素名称 | 描 述 | 备 注 |
select | 查询语句,最常用、最复杂的元素之一 | 可以自定义参数,返回结果集等 |
insert | 插入语句 | 执行后返回一个整数,代表插入的行数 |
update | 更新语句 | 执行后返回一个整数,代表更新的行数 |
delete | 删除语句 | 执行后返回一个整数,代表删除的行数 |
sql | 定义一部分SQL,在多个位置被引用 | 例如,一张表列名,一次定义,可以在多个SQL语句中使用 |
resultMap | 用来描述从数据库结果集中来加载对象,是最复杂、最强大的元素 | 提供映射规则 |
<!-- 根据uid查询一个用户信息 -->
<select id="selectUserById" parameterType="Integer"
resultType="com.po.MyUser">
select * from user where uid = #{uid}
</select>
<select>元素的常用属性
属性名称 | 描 述 |
id | 它和Mapper的命名空间组合起来使用,是唯一标识符,供MyBatis调用 |
parameterType | 表示传入SQL语句的参数类型的全限定名或别名。是个可选属性,MyBatis能推断出具体传入语句的参数。 |
resultType | SQL语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型。 返回时可以使用resultType或resultMap之一 |
resultMap | 它是映射集的引用,与< resultMap>元素一起使用。返回时可以使用resultType或resultMap之一 |
flushCache | 它的作用是在调用SQL语句后,是否要求MyBatis清空之前查询本地缓存和二级缓存。默认值为false。 如果设置为true,则任何时候只要SQL语句被调用,都将清空本地缓存和二级缓存 |
useCache | 启动二级缓存的开关。默认值为true,表示将查询结果存入二级缓存中 |
timeout | 用于设置超时参数,单位是秒。超时将抛出异常。 |
fetchSize | 获取记录的总条数设定 |
statementType | 告诉MyBatis使用哪个JDBC的Statement工作,取值为STATEMENT(Statement)、PREPARED(PreparedStatement)、CALLABLE(CallableStatement) |
resultSetType | 这是针对JDBC的ResultSet接口而言,其值可设置为FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLL_INSENSITIVE(双向滚动,及时更新) |
(1)使用Map接口传递多个参数(条件少的情况下)
在实际开发中,查询SQL语句经常需要多个参数,比如多条件查询。多个参数传递时,<select>元素的parameterType属性值的类型是什么呢?在MyBatis中允许Map接口通过键值对传递多个参数。
<!-- 查询陈姓男性用户信息 -->
<select id="selectAllUser" resultType="com.po.MyUser" parameterType="map">
select * from user
where uname like concat('%',#{u_name},'%')
and usex = #{u_sex}
</select>
(2)使用Java Bean传递多个参数(条件多的情况下)
<select id="selectAllUser" resultType="com.po.MyUser" parameterType="com.pojo.SeletUserParam">
select * from user
where uname like concat('%',#{u_name},'%')
and usex = #{u_sex}
</select>
<insert>元素用于映射插入语句,MyBatis执行完一条插入语句后,将返回一个整数表示其影响的行数。
keyProperty:该属性的作用是将插入或更新操作时的返回值赋值给PO类的某个属性,通常会设置为主键对应的属性。如果是联合主键,可以在多个值之间用逗号隔开。
keyColumn:该属性用于设置第几列是主键,当主键列不是表中的第一列时需要设置。如果是联合主键时,可以在多个值之间用逗号隔开。
useGeneratedKeys:该属性将使MyBatis使用JDBC的getGeneratedKeys()方法获取由数据库内部生产的主键,如MySQL、SQL Server等自动递增的字段,其默认值为false。
(1)主键(自动递增)回填
MySQL、SQL Server等数据库的表格可以采用自动递增的字段作为主键。
<!-- 添加一个用户,成功后将主键值回填给uid(po类的属性)-->
<insert id="addUser" parameterType="com.po.MyUser"
keyProperty="uid" useGeneratedKeys="true">
insert into user (uname,usex) values(#{uname},#{usex})
</insert>
(2)自定义主键
如果实际工程中使用的数据库不支持主键自动递增(如Oracle),或者取消了主键自动递增的规则时,可以使用MyBatis的<selectKey>元素来自定义生成主键。
<insert id="insertUser" parameterType="com.po.MyUser">
<!-- 先使用selectKey元素定义主键,然后再定义SQL语句 -->
<selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
select if(max(uid) is null, 1 , max(uid)+1) as newUid from user
</selectKey>
insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex})
</insert>
<!-- 修改一个用户 -->
<update id="updateUser" parameterType="com.po.MyUser">
update user set uname = #{uname},usex = #{usex} where uid = #{uid}
</update>
<!-- 删除一个用户 -->
<delete id="deleteUser" parameterType="Integer">
delete from user where uid = #{uid}
</delete>
<sql id="comColumns">uid,uname,usex</sql>
<select id="selectUser" resultType="com.po.MyUser">
select <include refid="comColumns"/> from user
</select>
<resultMap>元素表示结果映射集,是MyBatis中最重要也是最强大的元素。主要用来定义映射规则、级联的更新以及定义类型转化器等。
(1)<resultMap>元素结构
<resultMap type="" id="">
<constructor><!-- 类在实例化时,用来注入结果到构造方法 -->
<idArg/><!-- ID参数,结果为ID -->
<arg/><!-- 注入到构造方法的一个普通结果 -->
</constructor>
<id/><!-- 用于表示哪个列是主键 -->
<result/><!-- 注入到字段或JavaBean属性的普通结果 -->
<association property=""/><!-- 用于一对一关联 -->
<collection property=""/><!-- 用于一对多、多对多关联 -->
<discriminator javaType=""><!-- 使用结果值来决定使用哪个结果映射 -->
<case value=""/> <!-- 基于某些值的结果映射 -->
</discriminator>
</resultMap>
<resultMap>元素的type属性表示需要的POJO,id属性是resultMap的唯一标识。
子元素<constructor>用于配置构造方法(当POJO未定义无参数的构造方法时使用)。
子元素<id>用于表示哪个列是主键。
子元素<result>用于表示POJO和数据表普通列的映射关系。
子元素<association> 、<collection> 和<discriminator>是用在级联的情况下。
(2)使用Map存储结果集
<!-- 查询所有用户信息存到Map中 -->
<select id="selectAllUserMap" resultType="map">
select * from user
</select>
(3)使用POJO存储结果集
<!-- 使用自定义结果集类型 -->
<resultMap type="com.pojo.MapUser" id="myResult">
<!-- property是com.pojo.MapUser类中的属性-->
<!-- column是查询结果的列名,可以来自不同的表 -->
<id property="m_uid" column="uid"/>
<result property="m_uname" column="uname"/>
<result property="m_usex" column="usex"/>
</resultMap>
<!-- 使用自定义结果集类型查询所有用户 -->
<select id="selectResultMap" resultMap="myResult">
select * from user
</select>
如果表A中有一个外键引用了表B的主键,A表就是子表,B表就是父表。当查询表A的数据时,通过表A的外键,也将表B的相关记录返回,这就是级联查询。例如,查询一个人的信息时,同时根据外键(身份证号)也将他的身份证信息返回。
MyBatis如何处理一对一级联查询呢?在MyBatis中,通过<resultMap>元素的子元素<association>处理这种一对一级联关系。在<association>元素中,通常使用以下属性。 property:指定映射到实体类的对象属性。 column:指定表中对应的字段(即查询返回的列名)。 javaType:指定映射到实体对象属性的类型。 select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询。
例如:身份证号码,每个人的身份证号码只有一个。
在实际生活中一对多级联关系有许多,例如一个用户可以有多个订单,而一个订单只属于一个用户。 下面以用户和订单之间的关系为例,讲解一对多级联查询(实现“根据用户id查询用户及其关联的订单信息”的功能)的处理过程,读者只需参考该实例即可学会一对多级联查询的MyBatis实现。
其实,MyBatis没有实现多对多级联,这是因为多对多级联可以通过两个一对多级联进行替换。例如,一个订单可以有多种商品,一种商品可以对应多个订单,订单与商品就是多对多的级联关系。使用一个中间表订单记录表,就可以将多对多级联转换成两个一对多的关系。下面以订单和商品(实现“查询所有订单以及每个订单对应的商品信息”的功能)为例,讲解多对多级联查询。