全部章节 >>>>
本章目录
2.1 <insert>标签
2.1.1 <insert>标签简单应用
在Mybatis中的映射Mappe.xml中,可以使用<insert>标签实现增加数据。
<insert>标签常见属性如下:
属性名 |
作用 |
id |
对应接口中声明的增加方法名 |
parameterType |
对应增加方法接收参数类型 |
flushCache |
只要语句被调用,都会清空一级缓存和二级缓存 |
useGeneratedKeys |
使用JDBC的getGeneratedKeys()方法取出由数据库生成的主键 |
keyProperty |
通过getGeneratedKeys获取主键值后将要赋值的属性名 |
MyBatis<insert>标签实现增加功能步骤如下:
1、在接口中声明增加的抽象方法
2、在接口对应Mapper.xml中添加insert标签映射
示例:1、在UserMapper接口中增加一个抽象方法,代表具有增加数据功能
// 返回新增用户的记录数(影响的行数)
int addUser(SysUser user);
SysUser user接收实体对象,封装了要添加的数据
示例:2、在UserMapper.xml中添加该方法对应的sql语句映射: 使用<insert>标签定义增加sql语句
<insert id="addUser">
insert into sys_user(id,user_name,user_password,user_email,
user_info,head_img,create_time)
values(#{id},#{userName},#{userPassword},#{userEmail},
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})
</insert>
id为方法名
#号代表取实体对象中的属性名
特殊类型使用jdbcType说明
示例:3、测试类实现方法调用:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建一个SysUser对象
SysUser user = new SysUser();
user.setUserName("test1");
//设置user对象其他属性
// 正常情况下应该读入一张图片存到byte数组中,这里模拟字节数据
user.setHeadImg(new byte[] {1,2,3});
user.setCreateTime(new Date());
// 新增user对象到数据库中,result是执行SQL影响的行数
int result = userMapper.addUser(user);
// 提交事务,否则新增(更新)数据只存在于SqlSession中,会随着程序的关闭而消失
sqlSession.commit();
System.out.println("新增了"+result+"个用户"+",该用户的id="+user.getId());
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 获取接口代理对象
2.1.2 使用JDBC方式返回主键自增的值
在使用主键自增(例如,MySQL、SQL Server数据库)时,插入数据库后可能需要得到自增的主键值,然后使用这个值进行一些其他的操作。
新增addUser2方法,修改映射Xml文件,增加属性如下:
<insert id="addUser2" useGeneratedKeys="true" keyProperty="id">
insert into sys_user(user_name,user_password,user_email,user_info,head_img,create_time)
values(#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg,jdbcType=BLOB},
#{createTime,jdbcType=TIMESTAMP})
</insert>
得到生成的主键并且赋予对象的id属性
示例: 再次运行测试类实现方法调用:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建一个SysUser对象
SysUser user = new SysUser();
user.setUserName("test1");
//设置user对象其他属性
// 正常情况下应该读入一张图片存到byte数组中,这里模拟字节数据
user.setHeadImg(new byte[] {1,2,3});
user.setCreateTime(new Date());
// 新增user对象到数据库中,result是执行SQL影响的行数
int result = userMapper.addUser2(user);
// 提交事务,否则新增(更新)数据只存在于SqlSession中,会随着程序的关闭而消失
sqlSession.commit();
System.out.println("新增了"+result+"个用户"+",该用户的id="+user.getId());
addUser方法和addUser2方法接口声明一样,但是在Xml映射中,addUser2添加了useGeneratedKeys和keyProperty属性。
useGeneratedKeys会调用JDBC的getGeneratedKeys()方法取出生成的主键。 keyProperty将主键值赋予对象的id属性。
2.1.3 使用<selectKey>标签返回普通主键的值
useGeneratedKeys 用于获取自增的主键值,而有些数据库使用时并未使用自增功能,如Oracle使用序列等。
<selectKey> 标签来获取主键的值,这种方式对于是否提供主键自增功能的数据库均适用:
// 新增用户,使用selectKey方式
int addUser3(SysUser user);
修改UserMapper.xml对应的addUser3接口方法映射:
<insert id="addUser3">
insert into sys_user(user_name,user_password,user_email,user_info,head_img,create_time)
values(#{userName},#{userPassword},#{userEmail},#{userInfo},
#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
2.1.4 实践练习
2.2 <update>标签和<delete>标签
2.2.1 <update>标签用法
在MyBatis的Mapper.xml映射文件中,定义<update>标签用于对数据进行单个或批量更新,实现步骤如下:
示例:
1、在UserMapper接口中添加updateUser(SysUser user)方法:
UserMapper.xml中定义与之对应的SQL和配置
<update id="updateUser">
update sys_user set user_name=#{userName},user_password=#{userPassword},
user_email=#{userEmail},user_info=#{userInfo},head_img=#{headImg,jdbcType=BLOB},
create_time=#{createTime,jdbcType=TIMESTAMP} where id=#{id}
</update>
2、添加测试调用修改方法:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 获取一个SysUser对象
SysUser user = userMapper.selectById(1L);
// 修改SysUser对象信息
user.setUserName("admin2");
user.setUserEmail("admin2@mybatis.jack");
int result = userMapper.updateUser(user);
sqlSession.commit();
System.out.println("更新了"+result+"个用户信息");
2.2.2 <delete>标签用法
MyBatis的Mapper.xml中,定义<delete>标签用于对数据进行单个或批量更新。
示例:
1、在UserMapper接口中添加deleteUserById(Long id)方法,如下
<delete id="deleteUserById">
delete from sys_user where id=#{id}
</delete>
2、添加测试调用删除方法:
Long userId =15L; // 欲删除用户id
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int result = userMapper.deleteUserById(userId);
sqlSession.commit();
System.out.println("删除了"+result+"个用户");
2.2.3 删除具有主从关系的主表记录
实际应用中,为了保证数据的合理性,经常会创建外键和其他表主键进行关联约束,这时当我们删除主表记录时,如有数据约束,则会报错。
解决方案是设置从表的“删除时”规则为“置为NULL”或“级联”删除。
示例:
1、级联为例删除有角色关联的用户记录(先删除角色关联信息)
// 删除指定用户id的用户角色关联记录,返回受影响的行数
int deleteUserRolesByUserId(Long userId);
新定义一个UserRoleMapper.java接口
创建接口对应的UserRoleMapper.xml,增加删除配置,如下:
<delete id="deleteUserRolesByUserId" >
delete from sys_user_role where user_id=#{userId}
</delete>
2、添加测试调用删除有角色关联用户的方法:
Long userId =16L; // 欲删除用户id
UserRoleMapper userRoleMapper = sqlSession.getMapper(UserRoleMapper.class);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 删除从表用户角色关联记录
int cnt1 = userRoleMapper.deleteUserRolesByUserId(userId);
// 删除主表用户记录
int cnt2 = userMapper.deleteUserById(userId);
sqlSession.commit();
System.out.println("删除了"+cnt1+"条用户角色关联记录,删除了"+cnt2+"条员工记录");
2.2.4 实践练习
2.3 映射器方法多参数传递
2.3.1 MyBatis默认参数位置
目前案例接口中方法的参数只有一个,参数的类型可以分为两种,一种是基本类型,另一种是JavaBean。
在实际应用中经常会遇到使用多个参数的情况,可以将多个参数合并到一个JavaBean中,并使用这个JavaBean作为接口方法的参数,但是不适合于全部情况。
示例:
1、根据用户id和角色的enabled状态获取角色列表
// 在UserMappr接口中添加根据用户id和角色enabled状态获取用户的角色
List<SysRole> selectRolesByUserIdAndRoleEnabled(Long userId, Integer enabled);
// 在UserMappr.xml中添加根据用户id和角色enabled状态获取用户的角色
<select id="selectRolesByUserIdAndRoleEnabled" resultType="SysRole">
select r.id,r.role_name,r.enabled,r.create_by,r.create_time
from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u
on u.id=ur.user_id where u.id=#{userId} and r.enabled=#{enabled}
</select>
2、添加测试调用查询方法:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<SysRole> roles = userMapper.selectRolesByUserIdAndRoleEnabled(1L, 1);
for (SysRole role : roles) {
System.out.println("角色名:"+role.getRoleName()+",enabled:"+role.getEnabled());
}
这里运行报错,原因是无法识别多个参数
Mybatis映射器XML对于多个参数,默认情况下只识别arg0、arg1、paraml和param2这种内部定义的名称,
所以将参数名定义为#{arg0}和#{arg1}或者#{param1}和#{param2}即可解决错误,如下:
<select id="selectRolesByUserIdAndRoleEnabled" resultType="SysRole">
select r.id,r.role_name,r.enabled,r.create_by,r.create_time from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u on u.id=ur.user_id where u.id=#{param1} and r.enabled=#{param2}
</select>
u.id=#{param1} and r.enabled=#{param2} 这里参数名换成mybatis内部定义的
2.3.2 使用Map类型作封装参数
Map是键+值对形式数据格式集合,也可以解决多参数问题,通过key来映射Mapper.xml中SQL使用的参数名字,value用来存放参数值,需要多个参数时,通过Map的key-value方式来传递参数值,如下:
示例:
1、根据用户id和角色的状态(enabled字段)获取角色列表
将多个参数以Map形式封装传递
List<SysRole> selectRolesByUserIdAndRoleEnabledByMap(Map<String,Object> params);
Mybatis能够识别map中的key
<select id="selectRolesByUserIdAndRoleEnabledByMap" resultType="SysRole">
select r.id,r.role_name,r.enabled,r.create_by,r.create_time
from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u
on u.id=ur.user_id where u.id=#{userId} and r.enabled=#{enabled}
</select>
2、添加测试调用map传递参数的查询:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> paramsMap = new HashMap<String, Object>();
paramsMap.put("userId", 1L);
paramsMap.put("enabled", 1);
List<SysRole> roles = userMapper.selectRolesByUserIdAndRoleEnabledByMap(paramsMap);
for (SysRole role : roles) {
System.out.println("角色名:"+role.getRoleName()+",enabled:"+role.getEnabled());
}
创建Map对象,将传递的参数进行封装
传入map对象进行方法调用
2.3.3 使用注解类型作为参数
MyBatis还提供了对Mapper接口方法多个参数进行注解说明
参数前使用@Param(“参数名”)进行修饰:
示例:
1、根据用户id和角色的enabled状态获取角色列表
使用@Param注解进行参数名修饰说明
List<SysRole> selectRolesByUserIdAndRoleEnabledByAnnotation(@Param("userId")Long userId,
@Param("enabled")Integer enabled);
直接对应@Param修饰后的名称即可
<select id=" selectRolesByUserIdAndRoleEnabledByAnnotation" resultType="SysRole">
select r.id,r.role_name,r.enabled,r.create_by,r.create_time
from sys_role r join sys_user_role ur on r.id=ur.role_id join sys_user u
on u.id=ur.user_id where u.id=#{userId} and r.enabled=#{enabled}
</select>
如果映射器中的方法定义有多个参数,可以通过Map的key-value方式传递参数值来解决,但由于这种方式还需要自己手动创建Map以及对参数进行赋值,使用起来并不简洁,所以推荐使用@Param注解的方式来传递映射器中方法的多参数。
2.3.4 实践练习
2.4 MyBatis注解映射
2.4.1 MyBatis注解的基本用法
为了提高开发效率,MyBatis提供了另外一种注解的方式来实现接口方法的映射。
MyBatis注解方式就是将SQL语句直接写在接口方法上,常用包含@Select、@Insert、@Update、@Delete和@Provider五种,分别对应CRUD操作。
@Select(“select * from 用户表名”)
public List<User> selectUsrs();
对于需求比较简单的系统,其效率较高。缺点是当SQL有变化时,需要重新编译代码。一般情况下不建议使用注解方式
@Select注解用于查询数据
示例:
1、在RoleMapper中实现根据角色id查询角色信息对象
@Select("select id, role_name roleName, enabled, create_by createBy, "+
"create_time createTime from sys_role where id =#{id}")
SysRole selectRoleById1(Long roleId);
就是将以前写在Xml中的配置拿到了接口中
@Select注解查询时,默认情况下需要保证表中的列和实体中的属性名一致,如果存在表中下划线,而类中是驼峰命名时可以通过以下方式解决:
1、在主配置中开启驼峰命名设置
2、在@Select注解时使用 @Results注解进行说明,类似resultMap标签
@Results({
@Result(property="id",column="id",id=true),
@Result(property="roleName",column="role_name"),
@Result(property="enabled",column="enabled"),
@Result(property="createBy",column="create_by"),
@Result(property="createTime",column="create_time")
})
@Select("select id, role_name, enabled, create_by, create_time "
+ "from sys_role where id =#{id}")
SysRole selectRoleById2(Long roleId);
2.4.2 @Insert注解
@Insert注解用于新增数据
示例:
1、在RoleMapper中实现新增角色信息
@Insert("insert into sys_role(id,role_name,enabled,create_by,create_time) "
+ "values(#{id},#{roleName},#{enabled},#{createBy},"
+ "#{createTime,jdbcType=TIMESTAMP})")
int addRole(SysRole role);
就是将以前写在Xml中的sql配置拿到了接口中
2、在RoleMapper中实现新增角色信息,并且获取自增主键值
@Insert("insert into sys_role(role_name,enabled,create_by,create_time) "
+ "values(#{roleName},#{enabled},#{createBy},"
+ "#{createTime,jdbcType=TIMESTAMP})")
@Options(useGeneratedKeys=true, keyProperty="id")
int addRole2(SysRole role);
声明获取返回自增主键值,放入id属性中
2.4.3 @Update注解
@Update注解用于修改数据
示例:
1、使用注解修改角色信息,接收角色对象,返回影响行数
@Update("update sys_role set role_name=#{roleName}, enabled=#{enabled}, "
+ "create_by=#{createBy}, create_time=#{createTime,jdbcType=TIMESTAMP} where id=#{id}")
int updateRole2(SysRole role);
2.4.4 @Delete注解
@Delete注解用于删除数据
示例:
1、使用注解删除角色信息
@Delete("delete from sys_role where id=#{id}")
int deleteRoleById2(Long id);
2.4.5 @Provider注解
当SQL语句需要添加条件或过于复杂时,普通CRUD注解无法满足,需要使用Provider注解应对复杂的SQL处理,包括了以下几种:
@SelectProvider
@InsertProvider
@UpdateProvider
@DeleteProvider
几种注解用法一致,主要用于配合对应注解产生复杂的Sql语句时使用
示例:
使用@SelectProvider实现权限信息复杂查询
public interface PrivilegeMapper {
…
@SelectProvider(type=PrivilegeProvider.class, method="selectPrivilegeById2")
SysPrivilege selectPrivilegeById2(Long id);
}
public class PrivilegeProvider {
public String selectPrivilegeById2(final Long id) {
return new SQL() {
{
SELECT("id, privilege_name, privilege_url");
FROM("sys_privilege");
WHERE("id=#{id}");
}
}.toString();
}
}
2.4.4 实践练习
总结:
- MyBatis数据库操作时,需要先建立一个操作接口,声明操作的抽象方法,然后针对接口建立Mapper.xml映射文件,使用<insert><update><delete><select>标签分别完成对应方法Sql语句和参数、返回结果的配置。
- <insert>标签完成增加映射时,可以使用useGeneratedKeys、keyProperty获取主键自增产生的值,也可以使用<selectKey>的方式获取。
- 接口中方法如果接收多个参数时,可以采用默认参数名匹配,或者使用Map对参数进行封装,也可以使用@Param注解对参数进行修饰。
- 对于简单的系统操作,可以直接在接口方法上使用@Select、@Insert、@Update、@Delete注解完成Sql语句匹配,提高开发效率。