一、主键映射的作用
当数据插入操作不关心插入后数据的主键(唯一标识),那么建议使用 不返回自增主键值 的方式来配置插入语句,这样可以避免额外的SQL开销.
当执行插入操作后需要立即获取插入的自增主键值,比如一次操作中保存一对多这种关系的数据,那么就要使用插入后获取自增主键值的方式配置.
mybatis进行插入操作时,如果表的主键是自增的,针对不同的数据库相应的操作也不同。基本上经常会遇到的就是Oracle Sequece 和 Mysql 自增主键,解释如下
二、自动递增返回主键
一对多的那种表结构,在插入多端数据时,需要获取刚刚保存了的一端的主键。那么这个时候,上述的配置就无法满足需要了。为此我们需要使用mybatis提供的<selectKey />来单独配置针对自增逐渐的处理。
①Oracle Sequence配置
<sql id='TABLE_NAME'>TEST_USER</sql>
<sql id='TABLE_SEQUENCE'>SEQ_TEST_USER_ID.nextval</sql>
<!-- 注意这里需要先查询自增主键值 -->
<insert id="insertOrcle" parameterType="User">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select
<include refid="TABLE_SEQUENCE" />
from dual
</selectKey>
insert into
<include refid="TABLE_NAME" />
(ID,NAME,AGE) values ( #{id}, #{name}, #{age} )
</insert>
当使用了<selectKey />后,在实际的插入操作时,mybatis会执行以下两句SQL:
在执行插入 语句2 之前,会先执行 语句1 以获取当前的ID值,然后mybatis使用反射调用User对象的setId方法,将 语句1 查询出的值保存在User对象中,然后才执行 语句2 这样就保证了执行完插入后
@Test
public void testInsertOracle(){
User u=new User("小毛", 18);
int count = mapper.insertOrcle(u);
System.out.println(count>0?"新增成功":"新增失败");
System.out.println("新增主键是:"+u.getId());
}
②Mysql自增主键配置
针对于Mysql这种自己维护主键的数据库,可以直接使用以下配置在插入后获取插入主键
<sql id='TABLE_NAME'>TEST_USER</sql>
<insert id="insertMySql" useGeneratedKeys="true" keyProperty="id" parameterType="User">
insert into
<include refid="TABLE_NAME" />
( NAME, AGE ) values ( #{name}, #{age} )
</insert>
当然,由于Mysql的自增主键可以通过SQL语句
select LAST_INSERT_ID();
来获取的。因此针对Mysql,Mybatis也可配置如下:
<sql id='TABLE_NAME'>TEST_USER</sql>
<!-- 注意这里需要先查询自增主键值 -->
<insert id="insertMySql" parameterType="User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into
<include refid="TABLE_NAME" />
(ID,NAME,AGE) values ( #{id}, #{name}, #{age} )
</insert>
只不过该中配置需要额外的一条查询SQL!
三、关联映射作用
在现实的项目中进行数据库建模时,我们要遵循数据库设计范式的要求,会对现实中的业务模型进行拆分,封装在不同的数据表中,表与表之间存在着一对多或是多对多的对应关系。进而,我们对数据库的增删改查操作的主体,也就从单表变成了多表。那么Mybatis中是如何实现这种多表关系的映射呢?
查询结果集ResultMap
resultMap元素是 MyBatis中最重要最强大的元素。它就是让你远离90%的需要从结果 集中取出数据的JDBC代码的那个东西,而且在一些情形下允许你做一些 JDBC 不支持的事 情。
有人会问,之前的示例中我没有用到结果集,不是也可以正确地将数据表中的数据映射到Java对象的属性中吗?是的。这正是resultMap元素设计的初衷,就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们的关系。
resultMap元素中,允许有以下直接子元素:
- constructor - 类在实例化时,用来注入结果到构造方法中(本文中暂不讲解)
- id - 作用与result相同,同时可以标识出用这个字段值可以区分其他对象实例。可以理解为数据表中的主键,可以定位数据表中唯一一笔记录
- result - 将数据表中的字段注入到Java对象属性中
- association - 关联,简单的讲,就是“有一个”关系,如“用户”有一个“帐号”
- collection - 集合,顾名思议,就是“有很多”关系,如“客户”有很多“订单”
- discriminator(鉴别器) - 使用结果集决定使用哪个结果映射(暂不涉及)
每个元素的用法及属性我会在之后的博客中结合使用进行讲解。