Mybatis的增删改查
Mybatis的增删改查
增加数据<insert>
- 在增加数据的时候,mybatis默认返回的是受影响的行数,因此不需要指定
ResultType
指定返回类型 - 在
UserMapper.java
接口中添加方法
/**
@param user User对象
*/
Integer reg(User user);
-
UserMapper.xml
文件中添加<insert>
节点#{}
中填写的是User
对象的属性名称
<!-- 节点名称取决于需要执行的操作 -->
<!-- 例如增加操作应该使用insert节点 -->
<!-- id属性(*)的值是Java接口中的方法名称 -->
<!-- parameterType属性的值是参数类型
-->
<!-- 节点中间编写SQL语句 -->
<insert id="reg"
parameterType="cn.tedu.spring.entity.User">
INSERT INTO user (
username, password
) VALUES (
#{username}, #{password}
)
</insert>
- 测试
@Test
public void testReg() {
//加载Spring的配置文件
AbstractApplicationContext ac
= new ClassPathXmlApplicationContext(
"spring-mvc.xml",
"spring-dao.xml");
//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
UserMapper userMapper
= ac.getBean(
"userMapper", UserMapper.class);
//新建User对象
User user = new User();
user.setUsername("Tom1");
user.setPassword("123456");
//调用reg(user),进行添加,返回的是受影响的行数
Integer affectedRows
= userMapper.reg(user);
System.out.println(
"affectedRows=" + affectedRows);
ac.close();
}
在Mybatis中增加数据时获取自增主键的id
- 首先
mybatis
在处理增加数据的功能时,只是返回受影响的行数
,所以在持久层中并不会返回新增加的 - 如果需要获取自增主键
Id
,首先,在XML
映射的<insert>
节点中需要添加2
个属性useGeneratedKeys
:设置是否返回自增主键,如果为true
则返回,默认为false
keyProperty
: 配置自增主键在表中对应的字段 ,因为有时候在表中的自增主键的字段可能不是id
,因此需要指定
<!-- 节点名称取决于需要执行的操作 -->
<!-- 例如增加操作应该使用insert节点 -->
<!-- id属性(*)的值是Java接口中的方法名称 -->
<!-- parameterType属性的值是参数类型
useGeneratedKeys: 指定是否返回自增主键,默认为false
keyProperty:配置自增主键在表中对应的字段
-->
<insert id="reg"
parameterType="cn.tedu.spring.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (
username, password
) VALUES (
#{username}, #{password}
)
</insert>
- 此时的
mybatis
执行insert
方法之后,即是调用reg(user)
,返回的还是受影响的行数
,并不是此时的自增主键id
的值。而是在调用这个方法的时候将id
封装到指定的方法参数
中,即是封装到user
中了,因此只有调用者才可以获取id
,而持久层无法获取
@Test
public void testReg() {
//加载Spring的配置文件
AbstractApplicationContext ac
= new ClassPathXmlApplicationContext(
"spring-mvc.xml",
"spring-dao.xml");
//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
UserMapper userMapper
= ac.getBean(
"userMapper", UserMapper.class);
//新建User对象,此时并没有设置id的值
User user = new User();
user.setUsername("Tom1");
user.setPassword("123456");
//调用reg(user),进行添加,返回的是受影响的行数,但是此时已经将id封装到参数User对象中了
Integer affectedRows
= userMapper.reg(user);
System.out.println(
"affectedRows=" + affectedRows);
//直接获取Uesr对象中的id值,这个是自增主键返回的值
System.out.println("id = "+user.getId());
ac.close();
}
删除数据<delete>
-
在删除数据的时候,自动会返回受影响的行数,不需要在
delete
节点中定义返回类型,只有在查询数据的时候才会定义返回类型 -
在
UserMapper.java
中添加一个接口方法
//根据id删除数据,返回受影响的行数,返回1,如果删除失败返回0
Integer deleteUserById(int id);
- 在
UserMapper.xml
中配置<delete>
节点
<!-- 删除用户数据根据id
Integer deleteUserById(int id)
parameterType: 指定参数类型,这里也可以不需要指定
-->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
- 删除数据是不可逆的,通常不会真正的删除数据,我们会使用备份,日志等手段来保存数据,在许多软件上看到的删除也许都是
修改
操作,通常在表中有一个字段is_deleted
标记是否删除,如果执行删除,那么就会设置其值为true
表示已经删除了,那么此时将不会显示在客户端,让客户以为已经被删除了
Mybaits参数规则
mybatis
默认支持一个参数,即是定义的接口方法中只能有一个参数- 如果需要支持多个参数,那么需要使用
@Param()
注解 - 如果接口方法中的参数类型是基本类型的可以不用
parameterType
指定类型,如果不是基本类型的,规范要求需要使用parameterType
指定类型,但是可以不写
@Param()
- mybatis默认支持一个参数,即是定义的接口方法中只能有一个参数
- 在设计java接口方法时,如果需要指定多个参数,那么必须使用
@Param()
- 如果想要支持多个参数,需要使用
@Param()
来指定参数,比如Integer ChangePassword(@Param("id")Integer id,@Param("newPassword")String newPassword);
- 其中
@Param("key")
中的value
在配置增删改查的时候是使用#{key}
表达式取出的
- 其中
mybaits
在处理过程中,本质上是使用了Map
对参数进行了封装的。即是@Param("")
注解中给出的参数值是Map
中的key
,调用方法时给出的参数值是Map中的value
值,而最终在XML
文件中使用#{}
获取值,其实是使用Map中的get(key)
方法获取的
修改数据<update>
-
在修改数据的时候,mybatis自动返回受影响的行数,因此我们不需要定义返回类型,默认的返回数据就是受影响的行数
-
在
UserMapper.java
接口中定义根据id
修改数据的方法- 使用
@Param()
注解来标记多个参数
- 使用
/**
* 修改密码
* @param id id
* @param newPassword 新密码
* @return 受影响的行数
*/
Integer ChangePassword(@Param("id")Integer id,@Param("newPassword")String newPassword);
-
在
UserMapper.xml
中添加<update>
节点- 其中
#{}
表达式中的字段为@Param("value")
中的value
- 其中
<!-- 修改密码
Integer ChangePassword(@Param("id")Integer id,@Param("newPassword")String newPassword);
-->
<update id="ChangePassword">
update user set password=#{newPassword} where id=#{id}
</update>
- 测试方法
@Test
public void testChangePassword() {
//加载Spring的配置文件
AbstractApplicationContext ac
= new ClassPathXmlApplicationContext(
"spring-mvc.xml",
"spring-dao.xml");
//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
UserMapper userMapper
= ac.getBean(
"userMapper", UserMapper.class);
//调用删除的方法
int affectRow=userMapper.ChangePassword(3, "12345895");
System.out.println(affectRow);
ac.close();
}
案例:修改用户密码
用户提供数据
- 旧密码:
oldPassword
- 新密码:
newPassword
步骤
- 通过
id
查找用户信息- 不可以使用
select * from user where id=? and password=?
,因为这个是不区分大小写的,我们应该先根据id
获取用户信息,再比较password
- 在
UserserviceImpl
中完成验证逻辑,如果用户不存在,那么抛出用户不存在的异常,如果存在就验证原密码和是否匹配
- 不可以使用
- 用户信息存在,那么就要验证用户输入的
oldPassword
和用户信息中的原密码
是否相同了,如果不相同,抛出密码不匹配的异常
,如果相同,那么就可以修改密码 - 修改密码
实现
- 我们编写了一个
UserService
中编写逻辑
public void ChangePasssword(Integer id, String oldPassword,
String newPassword) throws UserNotFoundException, PasswordNotMatchException{
User user=this.findUserById(id); //获取用户信息
if (user==null) { //如果用户信息不存在
throw new UserNotFoundException("操作失败,用户信息不存在");
}else { //用户存在,则判断原密码
if (user.getPassword().equals(oldPassword)) {//如果密码匹配
userMapper.ChangePassword(id, newPassword); //修改密码
}else { //原密码不匹配
throw new PasswordNotMatchException("操作失败,原密码不正确");
}
}
}
- 那么在
Controller
中如果要调用这个ChangePasssword
将会通过处理异常来判断哪里是出错了,并给出友好的提示
查询数据<select>
单条数据的查询
- 根据
id
的查询返回的查询结果就是单条数据,比如:select * from user where id=1
- 单条记录的查询在编写
接口方法
的时候,只需要返回一个实体类对象
即可
/**
* 根据id查询用户信息
* @param id 用户id
* @return 返回User对象
*/
User findUserById(Integer id);
- 在
UserMapper.xml
中配置<select>
节点- 需要使用
resultType
指定返回的类型,因为参数是基本类型,因此不需要使用parameterType
指定参数类型
- 需要使用
<select id="findUserById" resultType="cn.tedu.spring.entity.User">
select * from user where id=#{id}
</select>
多条记录的查找
- 有些查找语句返回的是多条记录,那么我们可以使用
List<>
集合来接收返回的结果,不能直接使用实体类对象
来接收 - 在
UserMapper.java
中定义接口方法
/**
* 根据密码查找用户
* @param password 用户密码
* @return 返回的是一个用户的集合
*/
List<User> findUserByPassword(String password);
- 在
UserMapper.xml
中添加<select>
节点- 这里的
resultType
虽然返回的是User集合
,但是这里的类型还是需要写User类型 - 由于参数是基本类型,因此不需要使用
parameterType
- 这里的
<!--
List<User> findUserByPassword(String password);
resultType: 虽然返回的是User集合,但是这里的类型还是需要写User类型
-->
<select id="findUserByPassword" resultType="cn.tedu.spring.entity.User">
select * from user where password=#{password}
</select>
- 测试
@Test
public void testFindUserByPassword() {
//加载Spring的配置文件
AbstractApplicationContext ac
= new ClassPathXmlApplicationContext(
"spring-mvc.xml",
"spring-dao.xml");
//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
UserMapper userMapper
= ac.getBean(
"userMapper", UserMapper.class);
//获取User集合
List<User> users=userMapper.findUserByPassword("12345895");
System.out.println(users);
ac.close();
}
总结
xxMapper.xml
中配置的节点的id
要和xxMapper.java
中的方法名
相同- mybatis默认支持一个参数,但是我们可以使用
@Param("")
指定多个参数,不过在使用#{}
取值的时候要和@Param("")
中的参数一致 - 获取自增主键并不是作为方法的返回值,而是在调用方法的时候将自增主键的值设置在方法参数的对象中,那么此时的调用者就可以获取到
自增主键
的值 - 增加,修改,删除,方法返回的永远是受影响的行数
- **在定义实体类属性的时候,尽量使用
包装类
,比如Integer age**
- 只要是
<select>
节点,那么必须写返回类型resultType
,无论是基本型还是其他类型
如果觉得作者写的好,有所收获的话,点个关注,推荐一波,文章首发于公众号!!!