mybatis学习笔记8:注解开发

文章目录

  • 一、基于注解的开发环境搭建以及实现查询所有
    • 1.定义主配置文件
    • 2.准备实体类和Dao接口
    • 3.Dao接口定义findAll方法,以及添加注解
    • 4.测试类定义方法测试
    • 5.注解开发和基于xml的映射配置文件开发对比
    • 6.注解开发的一个小细节
  • 二、基于注解开发的单表的CRUD
    • 1.`IUserDao`的配置代码
    • 2.测试类的代码
  • 三、基于注解开发的单表查询的其他常用功能
    • 1.`IUserDao`的配置代码
    • 2.测试类的代码
  • 四、使用注解实现复杂关系映射开发
    • 1.当实体类的属性名和数据表的字段名不一致的解决方案
      • 1.1先修改实体类的属性名,重新生成相关方法
      • 1.2使用@Results和@Result这两个注解
    • 2.定义注解的时候,添加id属性值
    • 3.注解开发实现多对一(一对一)的查询配置
      • 3.1首选在账户实体类中建立映射属性
      • 3.2IAccountDao的注解配置
    • 4.注解开发实现一对多
      • 4.1实体类User中定义关系映射
      • 4.2IUserDao完善注解配置
      • 4.3测试:
  • 五、基于注解开发的二级缓存设置
    • 1.一级缓存都是默认开启的
    • 2二级缓存配置
      • 2.1主配置文件开启全局二级缓存
      • 2.2IUserDao开启二级缓存配置
      • 2.3测试方法
      • 2.4结果

一、基于注解的开发环境搭建以及实现查询所有

1.定义主配置文件

mybatis的注解开发是对于映射配置文件这个层面来说的,所以仍然需要定义主配置文件,和前文基于xml配置方法和细节,和注意事项完全一致

  • SqlMapConfig.xml
<configuration>
    
    <properties  resource="jdbcConfig.properties">
    properties>
    
    
    <typeAliases>
        
        <package name="com.xpt.domain"/>
    typeAliases>
    
    
    <environments default="mysql">
        <environment id="mysql">
            
            <transactionManager type="JDBC">transactionManager>
            
            <dataSource type="UNPOOLED">
                
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        
        
        <package name="com.xpt.dao"/>
    mappers>

configuration>

2.准备实体类和Dao接口

和前文使用的数据表,实体类保持一致
mybatis学习笔记8:注解开发_第1张图片

3.Dao接口定义findAll方法,以及添加注解

//    @Select(value = "select * from user")
    //只有一个参数时,value可以省略
    @Select("select * from user")
    List<User> findAll();

4.测试类定义方法测试

  • 代码
    public static void main(String[] args) throws Exception {
     

        //1.获取字节输入流
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.根据字节输入流构建 SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.利用factory生产一个SqlSession
        SqlSession sqlSession = factory.openSession();
        //4.利用sqlSession获取代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //5.利用代理对象 执行方法
        List<User> users = userDao.findAll();
        for (User user : users) {
     
            System.out.println(user);
        }
        //6.释放资源
        sqlSession.close();
        in.close();
    }
  • 结果:
    mybatis学习笔记8:注解开发_第2张图片
  • 上述就是基于注解开发的一个基本步骤
  • 下面 关注一些细节的问题

5.注解开发和基于xml的映射配置文件开发对比

mybatis学习笔记8:注解开发_第3张图片

6.注解开发的一个小细节

  • 只要使用的注解,就不能再建立对应的目录结构下建立IUserDao.xml配置文件了
  • 不然会报错
    mybatis学习笔记8:注解开发_第4张图片

二、基于注解开发的单表的CRUD

理解了前面的查询的过程,后面的内容都基本一致。

1.IUserDao的配置代码

    @Select("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);

    @Select("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
    void  updateUser(User user);

    @Select("delete from user where id=#{id}")
    void deleteUser(Integer userId);

2.测试类的代码

public class AnnotationCRUDTest {
     
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private IUserDao userDao;

    @Before
    public void init() throws Exception{
     
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After
    public void destroy() throws Exception{
     
        sqlSession.commit();
        sqlSession.close();
        in.close();
    }

    @Test
    public void testSave(){
     
        User user = new User();
        user.setUsername("mybatis annotation");
        user.setAddress("唐人街");

        userDao.saveUser(user);

    }

    @Test
    public void testUpdate(){
     
        User user = new User();
        user.setId(63);

        user.setUsername("update mybatis annotation");
        user.setAddress("唐人街 50号");

        userDao.updateUser(user);

    }

    @Test
    public void testDelete(){
     


        userDao.deleteUser(63);

    }
}
  • 经过测试,均能完成通过

三、基于注解开发的单表查询的其他常用功能

1.IUserDao的配置代码


    @Select("select * from user where id = #{id}")
    User findById(Integer userId);


    @Select("select * from user where username like '%${value}%' ")
    List<User> findUserByName(String username);


    @Select("select count(*) from user ")
    int findTotalUser();

2.测试类的代码

    @Test
    public void testFindById(){
     
        User user = userDao.findById(57);
        System.out.println(user);
    }


    @Test
    public  void testFindByName(){
     
//        List users = userDao.findUserByName("%mybatis%");
        List<User> users = userDao.findUserByName("mybatis");
        for(User user : users){
     
            System.out.println(user);
        }
    }

    @Test
    public  void testFindTotal(){
     
        int total = userDao.findTotalUser();
        System.out.println(total);
    }

四、使用注解实现复杂关系映射开发

1.当实体类的属性名和数据表的字段名不一致的解决方案

在基于xml的配置开发的时候,二者不一致的时候,使用的是一个map来解决,注解开发如何解决这个问题呢?

1.1先修改实体类的属性名,重新生成相关方法

1.2使用@Results和@Result这两个注解

  • 1.接口配置
  @Select("select * from user")
    @Results(value = {
     
            //id默认为false 这里指定为true是因为id为主键 column 数据表字段名 property 实体类属性名
            @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();
  • 2.执行testFindAll()方法
  @Test
    public  void testFindAll(){
     

        List<User> users = userDao.findAll();
        for(User user : users){
     
            System.out.println(user);
        }
    }
  • 3.结果:可以实现正常的结果
    在这里插入图片描述 - 4.测试testFindById()方法
    @Test
    public void testFindById(){
     
        User user = userDao.findById(57);
        System.out.println(user);
    }
  • 结果:没有封装成功,由于win10下mysql忽略大小写的缘故,显示了username
    在这里插入图片描述- 至于原因很简单,就是因为没有在该方法中进行相应的配置,那么问题来了,不可能每一个方法上都用那么大一串注解吧,
  • 所以基于注解的方式也可以使用userMap来完成一次定义,多处使用的效果

2.定义注解的时候,添加id属性值

mybatis学习笔记8:注解开发_第5张图片- 此时再测试findById()方法:就可以成功完成查询
在这里插入图片描述

3.注解开发实现多对一(一对一)的查询配置

这里同样使用用户和账户的实例来说明

3.1首选在账户实体类中建立映射属性


    //建立多对一(mybatis中称为 一对一)的映射 一个账户只能属于一个用户
    private User user;

    public User getUser() {
     
        return user;
    }

    public void setUser(User user) {
     
        this.user = user;
    }

3.2IAccountDao的注解配置

    /**
     * 查询account的信息 并同时查询所属的用户信息
     * @return
     */
    @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"),
            //下面把user的信息也封装进来
            @Result(
                    property = "user",
                    column = "uid",//在user表中当然是使用uid进行查询
                    //使用注解 @one 来指定一对一的关系 select是在user表中查询的全限定名加方法名
                    //后面 fetchType指定加载类型 LAZY延迟加载 EAGER立即加载
                    one = @One(select = "com.xpt.dao.IUserDao.findById",fetchType = FetchType.EAGER)
            )}
    )
    List<Account> findAll();
  • 注意点:
    mybatis学习笔记8:注解开发_第6张图片

4.注解开发实现一对多

查询用户,并查询出用户下所有的账户信息

4.1实体类User中定义关系映射

    //一对多关系映射 一个用户下 有多个账户
    List<Account> accounts;

    public List<Account> getAccounts() {
     
        return accounts;
    }

4.2IUserDao完善注解配置

  /**
     * 查询所有用户 并同时查询对应的账户信息
     * @return
     */
//    @Select(value = "select * from user")
    //只有一个参数时,value可以省略
    @Select("select * from user")
    @Results(id = "userMap",value = {
     
            //id默认为false 这里指定为true是因为id为主键 column 数据表字段名 property 实体类属性名
            @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"),
            @Result(
                    property = "accounts",//查询结果 封装到accounts属性
                    column = "id",//这里的id就是用户id
                    many = @Many(select = "com.xpt.dao.IAccountDao.findAccountByUid",
                            fetchType = FetchType.LAZY)
            )
    })
    List<User> findAll();

4.3测试:

  • 代码
    @Test
    public  void testFindAll(){
     

        List<User> users = userDao.findAll();
        for(User user : users){
     
            System.out.println("---用户查询信息---");
            System.out.println(user);
            System.out.println(user.getAccounts());

        }
    }

  • 结果:mybatis学习笔记8:注解开发_第7张图片

五、基于注解开发的二级缓存设置

1.一级缓存都是默认开启的

  • 代码
    @Test
    public void testFindById(){
     
        User user1 = userDao.findById(42);
        System.out.println(user1);


        User user2 = userDao.findById(42);
        System.out.println(user2);

        System.out.println(user1 == user2);


    }
  • 结果:
    mybatis学习笔记8:注解开发_第8张图片

2二级缓存配置

2.1主配置文件开启全局二级缓存

 
    <settings>
        <setting name="cacheEnabled" value="true"/>
    settings>

2.2IUserDao开启二级缓存配置

mybatis学习笔记8:注解开发_第9张图片

2.3测试方法

public class SecondLevelCacheTest {
     
    private InputStream in;
    private SqlSessionFactory factory;
//    private SqlSession sqlSession;
//    private IUserDao userDao;

    @Before
    public void init() throws Exception{
     
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
//        sqlSession = factory.openSession();
//        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After
    public void destroy() throws Exception{
     
//        sqlSession.commit();
//        sqlSession.close();
        in.close();
    }





    @Test
    public void testFindById(){
     
        SqlSession sqlSession = factory.openSession();
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        User user1 = userDao.findById(42);
        System.out.println(user1);

        //释放一级缓存
        sqlSession.close();

        //再次打开缓存
        SqlSession sqlSession1 = factory.openSession();
        IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
        User user2 = userDao1.findById(42);
        System.out.println(user2);

        sqlSession1.close();

        System.out.println(user1 == user2);

    }

2.4结果

  • 只完成一次数据库查询,第二次在缓存中查询

mybatis学习笔记8:注解开发_第10张图片

你可能感兴趣的:(JavaWeb,mybatis)