mybatis注解
注意:
当你表示了注解但是项目中的resources目录下还有该接口的xml文件,不管你用那个,用不用xml文件都会报错
注解实现CRUD操作
使用注解之后就不用再写接口相对应的xml配置文件,那么sql语句和一些实体类和数据库表中列的对应关系,以及多表查询和延迟加载都可以使用注解接口中来完成
在UserDao中完成方法的定义,以及sql语句的书写和相关映射配置
package com.itheima.dao;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface UserDao {
/*查找所有*/
@Select("select * from user")
List<User> findAll();
/*保存插入*/
@Insert("insert into user(username,sex,address,birthday)values(#{username},#{sex},#{address},#{birthday})")
void insertUser(User user);
@Update(" UPDATE USER SET username=#{username},sex=#{sex} WHERE id=#{id}")
/*更新操作*/
void updateUser(User user);
/*根据id删除*/
@Delete("delete from user where id=#{id}")
void deleteUser(Integer id);
/*根据名字模糊查询*/
@Select("select * from user where username like #{username}")
List<User> findUser(String name);
/*查找用户条数*/
@Select("select count(id) from user")
Integer findTotal();
}
之后在测试类中和之前一样直接调用方法即可。
使用注解开发:配置mybatis环境之后,建立实体类,然后再接口中定义方法,并用注解完成sql语句,最后在测试类中测试
mybatis注解建立实体类和数据库表中列的对应关系
当我们定义的实体类的属性名和数据库中的不一致时,我们也可以利用注解配置
代码演示:
/*查找所有*/
@Select("select * from user")
/*建立实体类和数据库表中列的对应关系
*column数据库表列名,property 实体类 */
@Results( id = "userMap",value = {
@Result(id = true,column = "id",property = "userId"),
@Result(column = "username",property = "userName"),
@Result(column = "address",property = "userAddress"),
@Result(column = "sex",property = "userSex"),
@Result(column = "birthday",property = "userBirthday"),
})
List<User> findAll();
在方法的上部进行注解
知识点:
1、@Results注释用来实现实体类属性名和数据库列名对应,定义id为了方便别人引用该对应关系,value里面写属性对应,用@Result
2、当只有一个值(Results)时,别人引用时value可以省略
3、别人引用用 @ResultMap注解,里面写@Results的id
eg: @ResultMap(value = {"userMap"})
或者
@ResultMap("userMap")
注解实现一对一映射
查询账户下的用户(一个账户只能被一个用户使用)
1、在实体类中建立关系
(在Account类中引入User对象)
2、在AccountDao中利用注解实现 账户下用户信息打印方法的调用, 以及使用延时加载还是立即加载配置
3、测试类调用方法,查看结果
代码演示:
1、(在Account类中引入User对象)
/*一对一关系映射,添加另一个对象引用
* 一对多的才添加对象集合*/
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
2、在AccountDao中利用注解实现 账户下用户信息打印方法的调用, 以及使用延时加载还是立即加载配置
/*查询所有账户*/
@Select("select * from account")
@Results(id = "accountMap" ,value = {
@Result(id = true,column = "ID",property = "id"),
@Result(column = "UID",property = "uid"),
@Result(column = "MONEY",property = "money"),
/*Account实体类里面的对象引用名称为user,要传递的参数是Account的uid,
因为是一对一关系,用one, select里面写的是用user的某个方法的全限定类名,fetchType里面的属性有延迟加载和立即加载,EAGER(渴望)是立即加载 */
@Result(property = "user" ,column = "uid",
one=@One(select = "com.itheima.dao.UserDao.findUserById",
fetchType = FetchType.EAGER))
})
List<Account> findAll();
重点摘录:
@Result(property = "user" ,column = "uid",
one=@One(select = "com.itheima.dao.UserDao.findUserById",
fetchType = FetchType.EAGER))
代码解释:
Account实体类里面的对象引用名称为user,要传递的参数是Account的uid,
因为是一对一关系,用one, select里面写的是用user的某个方法的全限定类名,fetchType里面的属性有延迟加载和立即加载,EAGER(渴望)是立即加载
知识点:
1、实现一对一或者多对一或者实体类和数据库的对应都是使用@Results里面的@Result
2、一对一就用one=@One(select=" ", fetchType =...)
select用来写调用 关联对象的方法的全限定类名(包名+类名+方法名)来实现打印关联对象的信息。
fetchType用来写加载方式
注解实现一对多映射
查询用户下的账户
和上述一对一映射不同之处就是在实体类中引入的是关联对象的集合,以及注解中用的是many
1、在User类中引入Account的对象集合
/*一对多映射,引用多的对象集合*/
private List<Account> accountList;
public List<Account> getAccountList() {
return accountList;
}
public void setAccountList(List<Account> accountList) {
this.accountList = accountList;
}
2、在UserDao中利用注解完成配置
/*查找所有*/
@Select("select * from user")
/*建立实体类和数据库表中列的对应关系
*column数据库表列名,property 实体类 */
@Results( id = "userMap",value = {
@Result(id = true,column = "id",property = "userId"),
@Result(column = "username",property = "userName"),
@Result(column = "address",property = "userAddress"),
@Result(column = "sex",property = "userSex"),
@Result(column = "birthday",property = "userBirthday"),
/*
property是User实体类引入Account对象集合的名称,column是user要传给方法的参数(!数据库中的名称!),
many是因为一个用户下可以有多个账户,里面配select的全限定类名和加载方式
* */
@Result(property = "accountList",column = "id",
many = @Many(select = "com.itheima.dao.AccountDao.findAccountByUid",
fetchType = FetchType.LAZY))
}
)
List<User> findAll();
重点摘录:
@Result(property = "accountList",column = "id",
many = @Many(select = "com.itheima.dao.AccountDao.findAccountByUid",
fetchType = FetchType.LAZY))
代码解释:
property是User实体类引入Account对象集合的名称,column是user要传给方法的参数(!数据库中的名称!),
many是因为一个用户下可以有多个账户,里面配select的全限定类名和加载方式
注解实现二级缓存
不管是注解还是xml一级缓存都是自动开启的,不用我们配置
开启二级缓存只需要在接口中引入一个注解即可----- 在接口名的上方
(因为主配置文件中的默认值都是开启二级缓存,所以不需要再配置主配置文件)
@CacheNamespace(blocking = true)
public interface UserDao {
知识点:开启二级缓存注解 @CacheNamespace
测试类编写:
@Test
public void testfindUserById(){
User user = userDao.findUserById(50);
System.out.println(user);
sqlSession.close();//关闭一级缓存
SqlSession sqlSession1 = factory.openSession();//再次开启sqlsession
UserDao userDao1 = sqlSession1.getMapper(UserDao.class);
User user1 = userDao1.findUserById(50);
System.out.println(user1);
System.out.println(user==user1);
}
结果截图:
![image-20210716121258705](https://pic-bed-1303913583.cos.ap-nanjing.myqcloud.com/img/image-20210716121258705.png)