十四、Mybatis 注解开发
14.1 入门案例(查询所有)
当我们使用注解的时候,不要保留 UserDao.xml 文件,否则会冲突。
UserDao.java
package com.cpz.dao;
import com.cpz.domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserDao {
@Select(value = "select * from user")
public List<User> findAll();
}
对比分析:
namespace 对应 package名+类名
id 对应 方法名
resultType 对应 List<User>中存放的User
select标签中的sql 对应 @Select中的sql
14.2 注解说明
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态SQL映射
14.3 注解实现基本的CRUD
14.3.1 @Select:实现查询
查询的实现在入门案例里已经完成,这里不再说明。
14.3.2 @Insert:实现新增
UserDao.java
@Insert(value = "insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})")
@SelectKey(keyProperty = "id",keyColumn = "id",before = false,statement = "select last_insert_id()",resultType = Integer.class)
public void saveUser(User user);
为了能返回添加用户的id,我们添加了一个 @SelectKey 注解
MybatisTest.java
@Test
public void saveUser(){
User user = new User();
user.setUsername("哪吒");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("天庭");
System.out.println(user);
userDao.saveUser(user);
System.out.println(user);
}
14.3.3 @Update:实现更新
UserDao.java
@Update(value = "update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}")
public void updateUser(User user);
MybatisTest.java
@Test
public void updateUser(){
User user = new User();
user.setId(57);
user.setUsername("杨戬");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("钱塘关");
userDao.updateUser(user);
}
14.3.4 @Delete:实现删除
UserDao.java
@Delete(value = "delete from user where id = #{id}")
public void deleteUser(Integer id);
MybatisTest.java
@Test
public void deleteUser(){
userDao.deleteUser(58);
}
14.3.5 其他操作
UserDao.java
// 根据id查询用户
@Select(value = "select * from user where id=#{id}")
public User findById(Integer id);
// 根据用户名称模糊查询
// @Select(value = "select * from user where username like #{username}")
@Select(value = "select * from user where username like '%${value}%'")
public List<User> findByLikeName(String username);
// 查询总用户数量
@Select(value = "select count(*) from user")
public Integer findCount();
// 传递多个条件:方案一:传递JavaBean使用ognl的方式解析
@Select(value = "select * from user where username like #{username} and sex = #{sex}")
public List<User> findByNameAndSex1(User user);
// 传递多个条件:方案二:传递2个字符串,在Dao中使用@Param
@Select(value = "select * from user where username like #{username} and sex = #{sex}")
public List<User> findByNameAndSex2(@Param(value = "username") String username,@Param(value = "sex") String sex);
// 传递多个条件:方案三:在Dao中使用Map集合的key解析
@Select(value = "select * from user where username like #{username} and sex = #{sex}")
public List<User> findByNameAndSex3(Map<String,Object> map);
MybatisTest.java
// 根据id查询用户
@Test
public void findById(){
User user = userDao.findById(48);
System.out.println(user);
}
// 根据用户名称模糊查询
@Test
public void findByLikeName(){
//List<User> list = userDao.findByLikeName("%王%");
List<User> list = userDao.findByLikeName("王");
for (User user : list) {
System.out.println(user);
}
}
// 查询总用户数量
@Test
public void findCount(){
Integer count = userDao.findCount();
System.out.println(count);
}
// 传递多个条件:方案一:传递JavaBean使用ognl的方式解析
@Test
public void findByNameAndSex1(){
User user = new User();
user.setUsername("%王%");
user.setSex("男");
List<User> list = userDao.findByNameAndSex1(user);
for (User u : list) {
System.out.println(u);
}
}
// 传递多个条件:方案二:传递2个字符串,在Dao中使用@Param
@Test
public void findByNameAndSex2(){
List<User> list = userDao.findByNameAndSex2("%王%","男");
for (User user : list) {
System.out.println(user);
}
}
// 传递多个条件:方案三:在Dao中使用Map集合的key解析
@Test
public void findByNameAndSex3(){
Map<String,Object> map = new HashMap<String, Object>();
map.put("username","%王%");
map.put("sex","男");
List<User> list = userDao.findByNameAndSex3(map);
for (User user : list) {
System.out.println(user);
}
}
14.4 注解实现复杂关系映射
14.4.1 @Result和@ResultMap
为了使代码效果更好,我们先将User类中的属性修改,使之与数据库的字段不一致
User.java
public class User implements Serializable{
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
// set、get方法
}
UserDao.java
@Results(id = "userMap",value = {
@Result(id = true,property = "userId",column = "id"),
@Result(property = "userName",column = "username"),
@Result(property = "userBirthday",column = "birthday"),
@Result(property = "userSex",column = "sex"),
@Result(property = "userAddress",column = "address")
})
@Select("select * from user")
public List<User> findAll();
@Select(value = "select * from user where id = #{id}")
@ResultMap(value = "userMap")
public List<User> findById(Integer id);
MybatisTest.java
@Test
public void findAll(){
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
}
@Test
public void findById(){
List<User> list = userDao.findById(48);
for (User user : list) {
System.out.println(user);
}
}
总结:
@Results注解代替的是标签<resultMap>
该注解中可以使用单个@Result注解,也可以使用@Result集合
@Results({@Result(),@Result()})或@Results(@Result())
@Result注解代替了 <id>标签和<result>标签
@Result 中 属性介绍:
id boolean类型,是否是主键,默认是false(非主键)
column 数据库的列名
property 对象中需要装配的属性名
one 需要使用的@One注解(@Result(one=@One)()))
many 需要使用的@Many注解(@Result(many=@many)()))
14.4.2 @One
@One注解(一对一)代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
@Result(column=" ",property="",one=@One(select=""))
首先,我们要创建一个 Account 实体类和 AccountDao.java 接口
Account.java
public class Account {
private Integer id;
private Integer uid;
private String money;
private User user;
//set、get方法
//toString
}
AccountDao.java
package com.cpz.dao;
import com.cpz.domain.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface AccountDao {
@Results(id = "accountUserMap",value = {
@Result(id = true,property = "id",column = "id"),
@Result(property = "uid",column = "uid"),
@Result(property = "money",column = "money"),
@Result(property = "user",column = "uid",one = @One(select = "com.cpz.dao.UserDao.findById",fetchType = FetchType.LAZY))
})
@Select(value = "select * from account")
public List<Account> findAccountUser();
}
MybatisTest.java
@Test
public void findAccountUser(){
List<Account> list = accountDao.findAccountUser();
for (Account account : list) {
System.out.println(account);
}
}
总结:总的来说相比于前面讲延迟加载时所使用的的代码并无太大不同,只是将 select = "com.cpz.dao.UserDao.findById"
放入 @One 注解里。
14.4.3 @Many
@Many注解(一对多)代替了<collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList)但是注解中可以不定义;
@Result(property="",column="",many=@Many(select=""))
User.java
public class User implements Serializable{
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
private List<Account> accounts;
// set、get方法
// toString
}
UserDao.java
@Select(value = "select * from user")
@Results(id = "userAccountMap",value = {
@Result(id = true,property = "userId",column = "id"),
@Result(property = "userName",column = "username"),
@Result(property = "userBirthday",column = "birthday"),
@Result(property = "userSex",column = "sex"),
@Result(property = "userAddress",column = "address"),
@Result(property = "accounts",column = "id",many = @Many(select = "com.cpz.dao.AccountDao.findById",fetchType = FetchType.LAZY))
})
public List<User> findUserAccount();
AccountDao.java
@Select(value = "select * from account where uid = #{id}")
public List<Account> findById(Integer uid);
MybatisTest.java
@Test
public void findUserAccount(){
List<User> list = userDao.findUserAccount();
for (User user : list) {
System.out.println(user);
}
}
@Many:相当于<collection>的配置
select 属性:代表将要执行的sql语句 fetchType 属性:代表加载方式,一般如果要延迟加载都设置为LAZY的值 column = "id":表示拿主键作为参数,去Account表去查询。
14.5 使用注解配置二级缓存
配置UserDao.java:@CacheNamespace(blocking = true)