前面进行了 Mybatis 的工具类的抽取,主要提取的是建立 SqlSession 的代码部分。java
如今来介绍一下 Mybatis 的 update、delete、insert 操做。web
update 操做sql
编写修改用户 id 为 2 的用户信息的测试类:数据库
@Test
void testUpdate(){
SqlSession session = MybatisUtil.getSession();
User userUpdate = new User();
userUpdate.setId(2L);
userUpdate.setName("用户2-afterUpdate");
userUpdate.setSalary(new BigDecimal(100));
session.update("com.mxz.mybatis.mapper.UserMapper.update", userUpdate);
session.close();
}
复制代码
update 方法的两个参数含义分别是:session
第一个是经过 mapper.xml 映射文件的命名空间(namespace)+ SQL 元素 id,来找到对应的更新 SQL 语句。mybatis
第二个是传入该 SQL 语句中要更新的用户信息的对象。app
在 UserMapper 映射文件中编写相应的 SQL 语句:dom
<update id="update" parameterType="com.mxz.mybatis.domain.User">
UPDATE t_user SET name = #{name}, salary = #{salary} WHERE id = #{id}
</update>
复制代码
这里有两点要注意:工具
0、update 元素的 parameterType 属性能够不用写,Mybatis 能够自动推断出传入的参数类型。学习
一、#{name}、#{salary}、#{id} 这些 OGNL 表达式中的名称要跟 User 对象的属性名称一致,否则会报错说反射异常,在 User 类中找不到对应的 getter 方法。
运行测试用例后能够看到控制台打印的日志 SQL:
DEBUG [main] - ==> Preparing: update t_user set name = ?, salary = ? where id = ?
DEBUG [main] - ==> Parameters: 用户2-afterUpdate(String), 10000(BigDecimal), 2(Long)
DEBUG [main] - <== Updates: 1
复制代码
第一行是生成的带有占位符的预编译处理语句。
第二行是与占位符对应的传入的参数值。
第三行是 DML 语句结果显示,说明受影响的行数为 1 行。
执行成功后,可是发现数据库中对应的数据并无更新,为何呢?
很明显是事务没有提交的问题致使的。
其中缘由是咱们在建立 SqlSession 的时候没有开启自动提交事务。
须要开启的话,在 openSession() 方法中传入ture 就能够了:
public class MybatisUtil {
private static SqlSessionFactory factory;
static {
InputStream in = null;
try {
in = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
factory = new SqlSessionFactoryBuilder().build(in);
}
// 返回一个SqlSession对象
public static SqlSession getSession(){
return factory.openSession(true);
}
}
复制代码
或者测试用例中手动提交事务:
@Test
void testUpdate(){
SqlSession session = MybatisUtil.getSession();
User userUpdate = new User();
userUpdate.setId(2L);
userUpdate.setName("用户2-afterUpdate");
userUpdate.setSalary(new BigDecimal(100));
session.update("com.mxz.mybatis.mapper.UserMapper.update", userUpdate);
// 提交事务
session.commit();
session.close();
}
复制代码
delete 操做
编写删除用户 id 为 1 的用户信息的测试类:
@Test
void testDelete(){
SqlSession session = MybatisUtil.getSession();
session.delete("com.mxz.mybatis.mapper.UserMapper.delete", 1L);
session.commit();
session.close();
}
复制代码
对应的 SQL 为:
<delete id="delete">
delete from t_user where id = #{id}
</delete>
复制代码
parameterType 属性能够不用写,Mybatis 能够自动推断出。
删除操做传入的参数为基本类型,因此 SQL 语句中的 OGNL 表达式 #{id} 的内容能够乱写成任意内容,如 #{ooxx},但为了规范,见名知意,咱们通常写对应的属性名称。
insert 操做
编写新增一个用户的测试类:
@Test
void testSave(){
SqlSession session = MybatisUtil.getSession();
User u = new User();
u.setName("用户-新增");
u.setSalary(new BigDecimal(100));
System.out.println(u);
session.insert("com.mxz.mybatis.mapper.UserMapper.save", u);
session.commit();
session.close();
System.out.println(u);
}
复制代码
对应的 SQL 为:
<insert id="save">
insert into t_user (name, salary) values (#{name}, #{salary})
</insert>
复制代码
insert 元素中的 parameterType 属性能够不写,以及 OGNL 表达式中的内容要与 User 类中的属性名称一致,由于传入的参数为 User 类对象。
对于 insert 操做,在开发中通常有以下需求:
保存一条新增的数据以后,须要获得刚刚保存数据生成的主键的值。
由于咱们在设计数据库表的时候,主键通常是作成自动生成自动递增的,并且程序中业务逻辑每每比较多,须要拿到该条数据的主键进行其余的操做。
那如何来获取自动生成的主键呢?
回忆一下,咱们在使用 JDBC 的时候,使用 Connection 建立 prepareStatement,有两种方式,一种是 connection.prepareStatement(String sql);只传入一个参数 SQL 语句的建立预编译处理语句的方法。
还有一种是 connection.prepareStatement(String sql, int autoGenKeyIndex);须要传入 SQL 语句,和是否应该返回自动生成的键的标志。
使用第二种方法返回自动生成的主键以后,而后经过 getGeneratedKeys() 来获取主键的值。
那在 Mybatis 中如何操做呢?
很简单,看 Mybatis 官方文档的说明:
使用 useGeneratedKeys 和 keyProperty 两个属性。
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into t_user (name, salary) values (#{name}, #{salary})
</insert>
复制代码
useGeneratedKeys 属性:是否须要返回自动生成的主键。
keyProperty 属性:把自动生成的主键值设置到对象的哪一个属性上。
执行成功后,打印传入的 User 对象,看到属性 id 已经有值了,而后经过 getId() 方法就能够获取主键的值了。
tips:查看官方文档是学习一门新语言最有效的方法。
系列预告:Mybatis 系列 8:Mybatis 的 typeAlias 别名配置。