Mybatis框架——入门2(注解开发)

这篇博客介绍了Mybatis注解开发的入门知识,包括环境搭建、单表CRUD操作(代理DAO方式)、多表查询(多对一/一对一/一对多)以及缓存配置。在单表操作中,讲解了@Select等注解的使用,而在多表查询部分,详细阐述了立即加载和延迟加载的区别,以及如何通过@Results和@ResultMap处理结果集映射。最后,对一级缓存和二级缓存进行了配置和解释。
摘要由CSDN通过智能技术生成

一、环境搭建

详情见入门篇1
额外:
在配置主配置文件时,在Mapper的配置中可以使用package直接将dao包下的所有mapper打包注册,不用一个一个注册。
<mappers> <package name="com.Yu.dao"/> </mappers>

二、单表CRUD操作(代理dao方式)

mybatis一共有四种注解分别为:
@Select @Insert @Update @Delete在注解后就可以添加sql语句的操作

1、实例

在配置好的情况下CRUD操作如下所示:
1.dao类

public interface IUserDao {
    //查询所有用户
    @Select("select * from user")
    List<User> findAll();

    //保存用户
    @Insert("insert into user(username,address,sex,birthday)" +
            "values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);


    //更新用户
    @Update("update user set username=#{username}," +
            "sex=#{sex},birthday=#{birthday},address=#{address} " +
            "where id=#{id}")
    void updateUser(User user);

    //删除用户
    @Delete("delete from user where id=#{id}")
    void  deleteUser(Integer userId);


    //根据id查询用户
    @Select("select * from user where id=#{id}")
    User findById(Integer userId);

    //根据用户名称模糊查询
    @Select("select * from user where username like #{username}")
    List<User> findUsernameByName(String username);

    //查询总用户数量
    @Select("select count(*) from user")
    int findTotal();
}

2、对应测试操作
其中Before,和After注解完成 配置读取、SqlSessionFactroyBuilder、SqlSessionFactroy、和SqlSession,进而动态代理原方法的过程。

public class AnnoCRUDTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;
    @Before
    public void init() throws IOException {
        in= Resources.getResourceAsStream("SqlMapConfig.xml");
        factory=new SqlSessionFactoryBuilder().build(in);
        session =factory.openSession();
        userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destory() throws IOException {
        session.commit();
        session.close();
        in.close();
    }
    
    @Test
    public void  testSave(){
        for (int i = 0; i < 20; i++) {
            User user = new User();
            user.setSex("男");
            user.setAdress("测试的");
            user.setUsername("胡无缺");
            userDao.saveUser(user);
        }
    }
    @Test
    public void  testUpdate(){
        User user = new User();
        user.setId(1);
        user.setUsername("SCCC");
        user.setAdress("earth");
        user.setSex("女");
        user.setBirthday(new Date());
        userDao.updateUser(user);
    }
    @Test
    public void  testDelete(){
        userDao.deleteUser(1);
    }
    @Test
    public void  testFindOne(){
        User user = userDao.findById(2);
        System.out.println(user);
    }
    @Test
    public void testFindByname(){
        List<User> users = userDao.findUsernameByName("%胡%");
        for (User user:users) {
            System.out.println(user);
        }
    }
    @Test
    public void testFindTotal(){
        int count = userDao.findTotal();
        System.out.println(count);
    }
}

2、结果集的对应(@Results() @ResultMap())

如果数据库表与实体类属性名称不对应怎么办?
答:可以使用@Results()注解一一对应,传入colmn代表数据库中的列名称,property代表实体类属性。

假设此时User对象的属性为userId,userName,userAddress,userSex,userBirthday而数据库user表中是id,username,address,sex,birthday。

	@Select("select * from user") //随便取的id
    @Results(id="userMap",value={
    			//为true表示为增值主键
            @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();

当下一个出现需要对应的方法时,只需要添加@ResultMap(value={“userMap”})
如:

  //查询所有用户
    @Select("select * from user")
    @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();


    //根据id查询用户
    @Select("select * from user where id=#{id}")
    @ResultMap(value = "userMap")
    User findById(Integer userId);

三、多表查询操作

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    }

假设新加了一个Account类,代表账户,它由id(主键),uid(userID),money,User对象,组成。
多个账户对应一个用户,这是多对一的关系,但Mybatis并没有这种,只有一对一关系,一对一也可以来实现多对多的关系。
一个用户有多个账户,这是一对多的关系。

1.立即加载与延迟加载
  1. 延迟加载:在使用数据时才发起查询,不用的时候不查。通常在一对多,多对多的关系中使用。

  2. 立即加载:不管使用不使用数据,只要一调用方法,马上发起查询。通常在多对一,一对一的关系中使用。

2.多对一/一对一(立即加载)

一对一的关系体现在,需要查询一个账户所持有的用户(一个账户对应一个用户),用到了联表查询。在账户中,可以拿到其userId,所以只需要再通过IUserDao中的findById()就可以拿到该账户所归属的用户。

同样通过@Results注解来配置返回的联表查询结果。
先在dao包的IAccountDao接口中,写Account的findAll()方法

IAccountDao{
	@Select("select * from account")
    //封装account自己的数据
    @Results(id="accountMap",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "uid",property = "uid"),
            @Result(column = "money",property = "money"),
            @Result(property = "user",column = "uid",one = @One(select = "com.itheima.dao.IUserDao.findById",fetchType = FetchType.EAGER))
    })
    List<Account> findAll();
    }
总结

总的来说最后一行@Result意思是 封装成user类,使用uid (column) ,是一对一关系 (one) ,去com.itheima.dao.IUserDao.findById查,使用立即加载 (fetchType)

3.一对多(延迟加载)

要想实现一对多那么User类要存在一个关系映射用来代表其拥有的账户,User实现类应如下

public class User implements Serializable {
    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
    //新加的
    private List<Account> accounts;}

一对多的关系体现在一个用户拥有多个账户

通过调用IUserDao接口中的findAll()方法,希望查出所有的用户,及每个用户的所有账户。
因为要根据用户Id查账户,所以在IAccountDao中也要写一个抽象方法如下:

//根据用户id查询账户信息
    @Select("select*from account where uid=#{userId}")
    List<Account> findAccountByUid(Integer userId);

所以IUserDao中的findAll()变为如下:

IUserDao{
   @Select("select * from user")
    @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"),
             @Result(property = "accounts",column = "id",many = @Many(select="com.itheima.dao.IAccountDao.findAccountByUid" ,fetchType = FetchType.LAZY))
    })
    List<User> findAll();

}
总结

总的来说,最后一行@Result表示,返回封装的是account类 (property) ,使用 id (column) 去com.itheima.dao.IAccountDao.findAccountByUid 查,是一个一对多的关系 (many) 。使用延迟加载 (fetchType = FetchType.LAZY)

四、缓存的配置

1.一级缓存

Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。
等于说只发起了一次查询

当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。

2.二级缓存

Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的 mapper映射文件内容,多个SqlSession共享。 Mybatis需要手动设置启动二级缓存。
通俗讲就是关闭一次Session,再发起Session。如果开启二级缓存,那么不会发起第二次查询请求。

配置步骤:

  1. 在主配置文件中写入
<settings>
	<setting name = "cacheEnabled" value="true"/>
</settings>
  1. 在想进行二级缓存的dao上使用@CacheNamespace的注解
@CacheNamespace(blocking=true)
public interface IUserDao{
......
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值