[慕课电商项目] 01.对 mybatis 逆向工程生成的 xm
一、insert 语句的总结
1. 插入的时候,如果插入了自增的id
- id值如果在该表中不存在,并且其他字段没有错误的话,mysql 会插入该行数据。
- 如果插入的 id 的值大于表自增的值,那么表自增的值就更新到这个id值。例如,表的自增主键在被手动插入后的最大的 id 值为100,那么下一个自动插入的 id 就递增到了101。
- id值在该表中已经存在了,那么就会报异常org.springframework.dao.DuplicateKeyException
2. 对返回值的处理
我们应该事先初始化一个值为0的 int 变量,然后对执行 insert 的方法进行 try-catch 异常捕获,根据是否捕获到异常来决定接下来怎么做。
3. 代码演示:
@Test
public void insertSelectiveWithoutTime() throws Exception {
//RandomUser.getNormalUser() 没有设置createTime, updateTime
//它们都为null
User user = RandomUser.getNormalUser();
//故意设置一个重复的 自增id,那么会捕获到异常,count 将为 0
//user.setId(90);
System.out.println(user);
int count = 0;
try {
count = userMapper.insertSelectiveWithoutTime(user);
}catch (Exception e) {
System.out.println("出现了异常: " + e);
}
System.out.println("count: " + count);
}
二、对 mybatis 逆向工程生成的 xml 的改进
1.问题缘由:
电商项目中数据库的每一张表都包含创建时间和更新时间字段,为什么所有的表都需要这两个字段呢?
- 好处:不仅可以简单的记录下操作时间,而且这两个字段也可以用于以后数据分析中。
- 必要性:
- 创建时间:大部分数据在创建了之后就不会更新了。
- 更新时间:如果数据需要大量的更新,那么我们也不可能记录每一次的更新时间,最好的方式是记录最后一次的更新时间。
2.思考点:
(1)创建时间和更新时间的值有必要交给 java 代码来做吗?
(2)让数据库去做这个是不是更适合,更方便些?
3.对 mybatis 逆向工程生成的映射文件的改进
(1) 分析
我们只需要修改 xml 中的 insert 和 update 语句即可。insert 语句插入的是一条全新的记录,我们要让数据库给出更新时间,创建时间的值。而对于 update 语句,我们只管最后的更新时间即可,创建时间已经在 insert 的时候插入到数据库中了。所以,数据库要给出更新时间的值,还要删掉原来 update 语句中的 create_time 的相关片段。在这里使用 mysql 的 now() 来生成时间。
注意: 在 mybatis 生成的 xml 中有一种 Selective 的实现。我们在 service 代码中也经常会调用它。这里的 insert 语句会包含(列名1,列名2,... ,列名n)values (值1,值2,... ,值n)。它根据传来的 pojo 的属性值是否为 null 来决定是否要更改数据库对应的那一列。
/* 列中包含的字段:(列名1,列名2,... ,列名n) */
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="username != null" >
username,
</if>
...
</trim>
/* values 中包含的字段:values (值1,值2,... ,值n) */
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
</if>
...
</trim>
我们要想,每次 insert 都一定要插入创建时间和更新时间的,而不是根据传来的 pojo 的 createTime ,updateTime 的值是否为null 来决定插入。所以,我们要在 Selective 类型的实现中,不让这两个属性 Selective ,而是直接确定好。
(createTime 和 updateTime 内心OS:这是不是有一种钦定的感觉?)
(2) 具体代码
(注意对应的列与值的位置,在更改的时候很容易搞混)
- 复杂的 insert
insert:
<insert id="insertWithoutTime" parameterType="top.kongk.mmall.pojo.User">
insert into mmall_user (id, username, password,email, phone, question, answer, role,
create_time, update_time)
values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},
#{phone,jdbcType=VARCHAR}, #{question,jdbcType=VARCHAR}, #{answer,jdbcType=VARCHAR}, #{role,jdbcType=INTEGER},
now(), now())
/*这两个 now() 对应 create_time 和 update_time*/
</insert>
insertSelective :
<insert id="insertSelectiveWithoutTime" parameterType="top.kongk.mmall.pojo.User" >
insert into mmall_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="username != null" >
username,
</if>
<if test="password != null" >
password,
</if>
<if test="email != null" >
email,
</if>
<if test="phone != null" >
phone,
</if>
<if test="question != null" >
question,
</if>
<if test="answer != null" >
answer,
</if>
<if test="role != null" >
role,
</if>
/*被钦定的 createTime 和 updateTime 的列名*/
create_time, update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
</if>
<if test="password != null" >
#{password,jdbcType=VARCHAR},
</if>
<if test="email != null" >
#{email,jdbcType=VARCHAR},
</if>
<if test="phone != null" >
#{phone,jdbcType=VARCHAR},
</if>
<if test="question != null" >
#{question,jdbcType=VARCHAR},
</if>
<if test="answer != null" >
#{answer,jdbcType=VARCHAR},
</if>
<if test="role != null" >
#{role,jdbcType=INTEGER},
</if>
/*被钦定的 createTime 和 updateTime 的值*/
now(), now(),
</trim>
</insert>
2.简单的 update
updateByPrimaryKey :
<update id="updateByPrimaryKey" parameterType="top.kongk.mmall.pojo.User" >
update mmall_user
set username = #{username,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
phone = #{phone,jdbcType=VARCHAR},
question = #{question,jdbcType=VARCHAR},
answer = #{answer,jdbcType=VARCHAR},
role = #{role,jdbcType=INTEGER},
/*被注释的 create_time = */
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
updateByPrimaryKeySelective :
<update id="updateByPrimaryKeySelective" parameterType="top.kongk.mmall.pojo.User" >
update mmall_user
<set >
<if test="username != null" >
username = #{username,jdbcType=VARCHAR},
</if>
<if test="password != null" >
password = #{password,jdbcType=VARCHAR},
</if>
<if test="email != null" >
email = #{email,jdbcType=VARCHAR},
</if>
<if test="phone != null" >
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="question != null" >
question = #{question,jdbcType=VARCHAR},
</if>
<if test="answer != null" >
answer = #{answer,jdbcType=VARCHAR},
</if>
<if test="role != null" >
role = #{role,jdbcType=INTEGER},
</if>
<!-- 被注释掉的 createTime
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
-->
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>