一膏萧、insert 語(yǔ)句的總結(jié)
1. 插入的時(shí)候冒窍,如果插入了自增的id
- id值如果在該表中不存在,并且其他字段沒有錯(cuò)誤的話烦租,mysql 會(huì)插入該行數(shù)據(jù)。
- 如果插入的 id 的值大于表自增的值除盏,那么表自增的值就更新到這個(gè)id值叉橱。例如,表的自增主鍵在被手動(dòng)插入后的最大的 id 值為100者蠕,那么下一個(gè)自動(dòng)插入的 id 就遞增到了101窃祝。
- id值在該表中已經(jīng)存在了,那么就會(huì)報(bào)異常org.springframework.dao.DuplicateKeyException
2. 對(duì)返回值的處理
??我們應(yīng)該事先初始化一個(gè)值為0的 int 變量踱侣,然后對(duì)執(zhí)行 insert 的方法進(jìn)行 try-catch 異常捕獲粪小,根據(jù)是否捕獲到異常來(lái)決定接下來(lái)怎么做大磺。
3. 代碼演示:
@Test
public void insertSelectiveWithoutTime() throws Exception {
//RandomUser.getNormalUser() 沒有設(shè)置createTime, updateTime
//它們都為null
User user = RandomUser.getNormalUser();
//故意設(shè)置一個(gè)重復(fù)的 自增id,那么會(huì)捕獲到異常探膊,count 將為 0
//user.setId(90);
System.out.println(user);
int count = 0;
try {
count = userMapper.insertSelectiveWithoutTime(user);
}catch (Exception e) {
System.out.println("出現(xiàn)了異常: " + e);
}
System.out.println("count: " + count);
}
二杠愧、對(duì) mybatis 逆向工程生成的 xml 的改進(jìn)
1.問(wèn)題緣由:
?? 電商項(xiàng)目中數(shù)據(jù)庫(kù)的每一張表都包含創(chuàng)建時(shí)間和更新時(shí)間字段,為什么所有的表都需要這兩個(gè)字段呢逞壁?
- 好處:不僅可以簡(jiǎn)單的記錄下操作時(shí)間流济,而且這兩個(gè)字段也可以用于以后數(shù)據(jù)分析中。
- 必要性:
- 創(chuàng)建時(shí)間:大部分?jǐn)?shù)據(jù)在創(chuàng)建了之后就不會(huì)更新了腌闯。
- 更新時(shí)間:如果數(shù)據(jù)需要大量的更新绳瘟,那么我們也不可能記錄每一次的更新時(shí)間,最好的方式是記錄最后一次的更新時(shí)間姿骏。
2.思考點(diǎn):
(1)創(chuàng)建時(shí)間和更新時(shí)間的值有必要交給 java 代碼來(lái)做嗎糖声?
(2)讓數(shù)據(jù)庫(kù)去做這個(gè)是不是更適合,更方便些分瘦?
3.對(duì) mybatis 逆向工程生成的映射文件的改進(jìn)
(1) 分析
?? 我們只需要修改 xml 中的 insert 和 update 語(yǔ)句即可姨丈。insert 語(yǔ)句插入的是一條全新的記錄,我們要讓數(shù)據(jù)庫(kù)給出更新時(shí)間擅腰,創(chuàng)建時(shí)間的值蟋恬。而對(duì)于 update 語(yǔ)句,我們只管最后的更新時(shí)間即可趁冈,創(chuàng)建時(shí)間已經(jīng)在 insert 的時(shí)候插入到數(shù)據(jù)庫(kù)中了歼争。所以,數(shù)據(jù)庫(kù)要給出更新時(shí)間的值渗勘,還要?jiǎng)h掉原來(lái) update 語(yǔ)句中的 create_time 的相關(guān)片段沐绒。在這里使用 mysql 的 now() 來(lái)生成時(shí)間。
?? 注意: 在 mybatis 生成的 xml 中有一種 Selective 的實(shí)現(xiàn)旺坠。我們?cè)?service 代碼中也經(jīng)常會(huì)調(diào)用它乔遮。這里的 insert 語(yǔ)句會(huì)包含(列名1,列名2取刃,... 蹋肮,列名n)values (值1,值2璧疗,... 坯辩,值n)。它根據(jù)傳來(lái)的 pojo 的屬性值是否為 null 來(lái)決定是否要更改數(shù)據(jù)庫(kù)對(duì)應(yīng)的那一列崩侠。
/* 列中包含的字段:(列名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 都一定要插入創(chuàng)建時(shí)間和更新時(shí)間的裸删,而不是根據(jù)傳來(lái)的 pojo 的 createTime ,updateTime 的值是否為null 來(lái)決定插入阵赠。所以涯塔,我們要在 Selective 類型的實(shí)現(xiàn)中,不讓這兩個(gè)屬性 Selective 清蚀,而是直接確定好匕荸。
?? (createTime 和 updateTime 內(nèi)心OS:這是不是有一種欽定的感覺?)
(2) 具體代碼
(注意對(duì)應(yīng)的列與值的位置枷邪,在更改的時(shí)候很容易搞混)
- 復(fù)雜的 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())
/*這兩個(gè) now() 對(duì)應(yīng) 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.簡(jiǎn)單的 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>