MyBatis 单表的增删改查
Posted Java Fans
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis 单表的增删改查相关的知识,希望对你有一定的参考价值。
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SSM 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:MyBatis 单表的增删改查
本文目录
通过上一篇文章的学习可了解到,MyBatis 可以方便的对数据库进行操作,而数据库表可能是一个相对独立的表(这里谓之单表),也可能两个或多个有密切联系的表(这里谓之多表),本文先来学习单表的增删改查操作,下一篇文章我们再来学习多表关联查询。
先来认识一下 SqlSession 的若干方法,这些方法被用来执行定义在 mapper 映射文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。以下是一些常用的方法。
- <T> T selectOne(String statement, Object parameter) 查询单条记录
- <E> List selectList(String statement, Object parameter) 查询记录集合
- <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) 查询记录封装成 Map 集合
- int insert(String statement, Object parameter) 插入一条记录
- int update(String statement, Object parameter) 修改一条记录
- int delete(String statement, Object parameter) 删除一条记录
上述方法中的第一个参数 statement 通常使用 namespace + id 的字符串,namespace 定位到唯一的 mapper 映射文件,id 定位到这个 mapper 映射文件指定的 SQL 语句。
第二个参数可以是原生类型(自动装箱或包装类)、JavaBean、POLO 或 Map,用于限定查询条件等。
其中 selectOne 和 selectList 的不同之处是 selectOne 必须返回一个对象,如果有多个对象,或者没有返回(或返回了 null),那么就会抛出异常。如果不确定返回了多少对象,就使用 selectList。
以上方法可以重载,第二个参数不是必要的,重载方法如下。
- <T> T selectOne(String statement)
- <E> List<E> selectList(String statement)
- <K,V> Map<K,V> selectMap(String statement, String mapKey)
- int insert(String statement)
- int update(String statement)
- int delete(String statement)
结果映射 ResultMap
所谓结果映射就是让数据表的字段名称(即列名)与 Java 实体类的属性名称一一进行关联匹配的一种机制,以便 MyBatis 查完数据库后能将关系型查询结果正确地封装为 Java 对象。如果数据库的字段名称跟相应的类的属性名称不一样,不作处理的话,mybatis 运行后相应的字段处的查询结果就为空。
在映射文件 UserMapper.xml 中,如果 SQL 查询语句使用别名了,则 <select> 节点中的 SQL 查询语句修改如下:
<select id="list" resultType="user">
select * from user
</select>
然后运行 UserMapperTest.java 测试类中的 testList 方法:
@Test
public void testList()
SqlSession sqlSession = factory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.list();
for (User user : list)
System.out.println("user = " + user);
运行结果如下:
可以发现查出来的数据为 null,这是因为数据表 user 的字段与对象 User 的属性名称不一致造成的。数据库查出来的数据无法封装到对应的对象属性中去。
解决办法有两个:
- 方法一:在 SQL 语句中使用别名,让查询结果字段与对象属性一致
- 方法二:利用结果映射 ResultMap
在 UserMapper.xml 中配置结果映射 ResultMap,代码如下:
<!--定义映射规则-->
<resultMap id="userMap" type="user">
<id column="u_id" property="id"></id>
<result column="u_name" property="userName"></result>
<result column="u_password" property="password"></result>
</resultMap>
<select id="list" resultMap="userMap">
select * from user
</select>
上面代码中,将原先的 resultType=“user” 改为了 resultMap=“userMap”,其中,userMap为 结果映射 resultMap 中的 id。
运行原有的测试类,效果如下:
可以正常输出了,没有出现 null 的情况,证明了结果映射成功。
使用 selectOne 方法查询单条记录
实现步骤:
【1】在 UserMapper.java 接口中新增一个方法:
User getById(Integer id);
【2】在映射文件 UserMapper.xml 中新增一段 select 语句:
<select id="getById" parameterType="int" resultMap="userMap">
select * from user where u_id=#id
</select>
其中,parameterType=“int” 表示参数的类型为整型,也可省略不用,MyBatis 会自动识别传进来的参数类型。此外仍然使用结果映射 resultMap。
<select> 标签中的 id 属性用于唯一标识该 SQL 语句,要与接口中方法名称一致。SQL语句中的 # :对指定参数类型属性值的引用。
【3】在测试类 UserMapperTest.java 中添加 testGetById 方法,代码如下:
@Test
public void testGetById()
SqlSession sqlSession = factory.openSession(true);
User user = sqlSession.selectOne("cn.kgc.mybatis.mapper.UserMapper.getById", 1);
System.out.println(user);
sqlSession.selectOne 方法,用于查询单条数据,其中第一个参数是 UserMapper.java 接口中 getById 方法的全限定名,第二个参数是 id 值。
运行结果如下:
使用 insert 方法添加记录
主键非自增长
实现步骤:
【1】检查数据库 user 表,将主键 u_id 改为非自增长,然后在 UserMapper.java 接口中新增一个方法。
int insertUser(User user);
【2】在映射文件 UserMapper.xml 中新增一段 insert 语句。
<!--添加一个用户-->
<insert id="insertUser" parameterType="user">
insert into user (u_id,u_name,u_password) values (#id,#userName,#password)
</insert>
parameterType=“user” 也可不加,MyBatis 会自动判断传进来的参数类型。#id 是占位符,传进来的值是参数类型 User 对应的同名属性值,即 User 对象的 id 属性的值,其他类推。
【3】在测试类 UserMapperTest.java 中添加 testGetById 方法,代码如下:
@Test
public void testInsertUser()
SqlSession sqlSession = factory.openSession(true);
User user=new User();
user.setId(4);
user.setUserName("武松");
user.setPassword("12345");
int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUser", user);
sqlSession.commit();
System.out.println(count);
这里用到 insert 方法,用于添加记录,返回受影响的行数。运行效果如下:
注意: 如果数据库中没有发现这条新纪录,可能是因为你没有使用 sqlSession.commit() 方法来实现事务提交。
主键值由数据库自增长
MySQL 数据库表的主键值在设置为自动增长的情况下,程序只需要添加除主键外的其他字段即可。但一般情况下程序中添加一个 User 对象后无法马上获得该对象的 id 属性值,需要一定的配置才行,具体步骤如下:
【1】修改 MySQL 数据库,设置 user 表的主键 u_id 自动增长。
注意:这里用的 MySQL 客户端是 SQLyog。
【2】在 UserMapper.java 接口中新增一个方法。
int insertUserAutoIncrement(User user);
【3】在映射文件 UserMapper.xml 中新增一段 insert 语句。
<!--添加一个用户,u_id自增-->
<insert id="insertUserAutoIncrement">
insert into user (u_name,u_password) values (#userName,#password)
</insert>
【4】在测试类 UserMapperTest.java 中添加 testInsertUserAuto 方法,代码如下:
@Test
public void testInsertUserAuto()
SqlSession sqlSession = factory.openSession(true);
User user=new User();
user.setUserName("武松");
user.setPassword("12345");
int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUserAutoIncrement", user);
sqlSession.commit();
if(count>0)
System.out.println("添加成功!");
System.out.println("新添加的学生编号是:"+user.getId());
运行结果如下:
可见添加时成功的,但添加后学生编号为0,即无法在添加完数据后立即回去主键的值,如何在数据添加成功后获取这个自增长的主键值呢?请看下一个步骤。
【5】修改映射文件,代码如下:
<!--添加一个用户,u_id自增-->
<insert id="insertUserAutoIncrement" parameterType="user"
keyProperty="id" useGeneratedKeys="true">
insert into user (u_name,u_password) values (#userName,#password)
</insert>
关键代码是 keyProperty=“id” useGeneratedKeys=“true”,其中,keyProperty 指的是实体类的某个属性接受接受主键返回的值,useGeneratedKeys 指的是使用自动生成的主键。
【6】二次测试,代码如下:
@Test
public void testInsertUserAuto()
SqlSession sqlSession = factory.openSession(true);
User user=new User();
user.setUserName("苏东坡");
user.setPassword("32154");
int count = sqlSession.insert("cn.kgc.mybatis.mapper.UserMapper.insertUserAutoIncrement", user);
sqlSession.commit();
if(count>0)
System.out.println("添加成功!");
System.out.println("新添加的用户编号是:"+user.getId());
二次测试结果如下:
可以发现,已经获取到新添加的用户的主键值。
使用 delete 方法删除记录
实现步骤:
【1】在 UserMapper.java 接口中新增一个方法 deleteUserById 如下:
int deleteUserById(Integer id);
【2】在映射文件 UserMapper.xml 中新增一段 delete 语句如下:
<!--删除一个用户-->
<delete id="deleteUserById">
delete from user where u_id=#id
</delete>
【3】在测试类 UserMapperTest.java 中添加 testDeleteUserById 方法,代码如下:
@Test
public void testDeleteUserById()
SqlSession sqlSession = factory.openSession(true);
int count = sqlSession.delete("cn.kgc.mybatis.mapper.UserMapper.deleteUserById", 4);
sqlSession.commit();
if(count>0)
System.out.println("删除成功!");
else
System.out.println("用户不存在!");
运行效果如下:
使用 update 方法修改记录
实现步骤:
【1】在 UserMapper.java 接口中新增一个方法 updateUserById 如下:
int updateUserById(User user);
【2】在映射文件 UserMapper.xml 中新增一段 update 语句如下:
<!--更新用户信息-->
<update id="updateUserById">
update user set u_name=#userName,u_password=#password where u_id=#id
</update>
【3】在测试类 UserMapperTest.java 中添加 updateUserById 方法,代码如下:
@Test
public void testUpdateUserById()
SqlSession sqlSession = factory.openSession(true);
User user=new User();
user.setUserName("苏东");
user.setPassword("123456");
user.setId(7);
int count = sqlSession.update("cn.kgc.mybatis.mapper.UserMapper.updateUserById", user);
sqlSession.commit();
if(count>0)
System.out.println("更新成功!");
else
System.out.println("用户不存在!");
运行效果如下:
模糊查询
实现步骤:
【1】在 UserMapper.java 接口中新增一个方法 findUserByName 如下:
List<User> findUserByName(String userName);
【2】在映射文件 UserMapper.xml 中新增一段 select 语句如下:
<!--根据姓名模糊查询-->
<select id="findUserByName" resultType="cn.kgc.mybatis.entity.User" resultMap="userMap">
select * from user where u_name like '%' #userName '%'
</select>
【3】在测试类 UserMapperTest.java 中添加 testFindUserByName 方法,代码如下:
@Test
public void testFindUserByName()
SqlSession sqlSession = factory.openSession(true);
List<User> list = sqlSession.selectList("cn.kgc.mybatis.mapper.UserMapper.findUserByName", "张");
for (User user : list)
System.out.println("user = " + user);
运行效果如下:
动态查询
在大家熟悉的网购中,筛选商品是一个非常重要的功能。筛选条件有很多,每个人选的条件都不一样,这里就用到了动态查询。前台页面把某个用户的筛选条件传到后台服务器,后台服务器根据筛选条件动态生成 SQL 语句,再从数据库中查找到合适商品。
动态 SQL 多用于解决查询条件不确定的情况,在程序运行期间,根据运行期间,根据用户提交的多种可能的查询条件进行查询,提交的查询条件不同,动态生成和执行的 SQL 语句也不同。动态 SQL 通过 MyBatis 提供的各种标签对条件做出判断以实现动态拼接 SQL 语句。
常用的动态 SQL 标签有 <if>、<where>、<set>、<choose/>、<foreach> 等。
映射文件 UserMapper.xml 中定义映射规则,代码如下:
<!--定义映射规则-->
<resultMap id="userMap" type="user">
<id column="u_id" property="id"></id>
<result column="u_name" property="userName"></result>
<result column="u_password" property="password"></result>
<result column="u_state" property="state"></result>
</resultMap>
if 标签
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段拼接到其所在的 SQL 语句中。
实现步骤:
【1】在接口 UserMapper.java 中 添加方法 selectUserIf 如下:
List<User> selectUserIf(@Param("userName") String userName, @Param("state") int state);
【2】在映射文件 UserMapper.xml 中添加一条 select 语句,代码如下:
<select id="selectUserIf" resultMap="userMap">
select * from user where 1=1
<if test="userName!=null">
and u_name like '%' #userName '%'
</if>
<if test="state!=null">
and u_state=#state
</if>
</select>
【3】在测试类 UserMapperTest.java 中添加 testSelectUserIf 方法,代码如下:
@Test
public void testSelectUserIf()
SqlSession sqlSession = factory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectUserIf("张", 1);
for (User user : users)
System.out.println("user = " + user);
查询姓名中含有“张”字,并且 state 状态为1的记录,结果如下:
where 标签
<if/>标签的中存在一个比较麻烦的地方,需要在 where 后手工添加 “1=1” 的子句。因为,若 where 后的所有<if/>条件均为 以上是关于MyBatis 单表的增删改查的主要内容,如果未能解决你的问题,请参考以下文章