day03-mybatis随堂笔记

day03-mybatis随堂笔记

一、mybatis的延迟加载

1.概念:

延迟加载也叫懒加载 一开始的时候不会进行加载,当真正需要的时候才开始加载执行

立即加载,不管什么情况都会一次性的全部加载出来

2.使用延迟加载或者立即加载的时机?

​ 按需加载:

​ 1.当查询账户的时候一定要关联查询用户,这个时候建议使用立即加载

​ 2.当查询用户的时候不需要立即关联账户,这个时候不需要立即加载,可以使用懒加载

3.在实际开发中级联查询的时候使用加载方式的时机?

​ 一对一,多对一 一般使用立即加载

​ 一对多,多对多 一般使用懒加载(延迟加载)

4.延迟加载的好处:

​ 节省内存资源,效率比较快

5.使用懒加载和立即加载:

5.1立即加载:

​ mybatis的默认加载方式就是立即加载

级联的另外一种方式配置,根据账户信息关联用户信息,一对一操作

第一步,编写IAccountDao

 List<Account> findAll();

第二步,编写IAccountDao.xml

    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一对一的关系映射:配置封装user的内容
        select属性指定的内容:查询用户的唯一标识:
        column属性指定的内容:用户根据id查询时,所需要的参数的值
        -->
        <association property="user" column="uid" javaType="user"
                     select="com.itheima.dao.IUserDao.findById">
        </association>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="accountUserMap">
        select * from account
    </select>

第三步,编写IUserDao

  User findById(Integer userId);

第四步,编写IUserDao.xml

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user">
        select * from user where id = #{uid}
    </select>

第五步,编写AccountTest测试类

   /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println("--------每个account的信息------------");
            System.out.println(account);
            System.out.println(account.getUser());
        }
    }
5.2懒加载:

要想是使用懒加载,必须不能使用多表联合查询的sql语句,必须使用单表查询语句

案例1:

​ 根据账户信息关联用户信息,一对一操作(基于上面的代码基础之上)

​ 第一步,在sqlMapConfig.xml中添加settings配置

  <!--配置参数-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>

        <setting name="lazyLoadTriggerMethods" value=""></setting>
    </settings>

第二步,测试

 @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        }

第三步,测试结果

延迟加载

[外链图片转存失败(img-q6emX1iW-1565187729641)(assets\1558753027820.png)]

立即加载

[外链图片转存失败(img-MbOLwhsh-1565187729645)(assets\1558753057125.png)]

案例2:

​ 根据用户信息关联账户信息,一对多操作(基于上面的代码基础之上)

第一步,开启延迟加载在sqlMapConfig.xml

  <!--配置参数-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>

        <setting name="lazyLoadTriggerMethods" value=""></setting>
    </settings>

第二步,编写IUserDao

List<User> findAll();

第三步,编写IUserDao.xml

    <!-- 定义User的resultMap-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account" 
                    select="com.itheima.dao.IAccountDao.findAccountByUid" column="id"></collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user
    </select>

第四步,编写IAccountDao

 /**
     * 根据用户id查询账户信息
     * @param uid
     * @return
     */
    List<Account> findAccountByUid(Integer uid);

第五步,编写IAccountDao.xml

  <!-- 根据用户id查询账户列表 -->
    <select id="findAccountByUid" resultType="account">
        select * from account where uid = #{uid}
    </select>

第六步,测试类UserTest

    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        }

延迟加载结果

[外链图片转存失败(img-Ts2j2VFo-1565187729647)(assets\1558754523139.png)]

立即加载结果

[外链图片转存失败(img-Ek0qJdWU-1565187729650)(assets\1558754589322.png)]

二、mybatis的缓存

​ 缓存是运行在内存中的临时数据的一种统称。

​ 缓存的意义是为了减少访问数据库的压力而存在的

​ mybatis的缓存分为一级缓存和二级缓存

​ 一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效

​ 二级缓存是mapper级别的缓存,同一个namespace共用这一个缓存,所以对SqlSession是共享的

一级缓存:

​ 如果从同一个sqlSession中生成实体类则是同一个内存中加载的,第一次的时候由于缓存中没有临时数据,那么就会从数据库中查询,第二次的时候就不在从数据库中查询了,从sqlSession缓存中查询。

​ 可以使用sqlSession.close()关闭缓存,或者sqlSession.clearCache();清空缓存

​ 当mybatis执行完修改,删除,和新增之后,那么当前sqlSession一级缓存就已经自动清空,这个时候再使用sqlSession一级缓存去查询,此时没有数据,mybatis就会自动去查询数据库。

问题:

​ 在一个sqlSessionFactory中可以创建多个sqlSession(一级缓存),一般情况下在一个项目中只允许有一个sqlSessionFactory

二级缓存:

​ 二级缓存是mapper级别的缓存,同一个namespace共用这一个缓存,所以对SqlSession是共享的

其实的真正执行者CachingExecutorExecutor**的装饰者

​ 使用步骤:

​ 第一步,在sqlMapConfig.xml中设置全局开启二级缓存的设置,默认就是开启

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

​ 第二步,在mapper标签中开启局部二级缓存

[外链图片转存失败(img-WQi2DRml-1565187729651)(assets\1558765694518.png)]


​ 第三步,在调用的sql语句所在的select标签中使用缓存

[外链图片转存失败(img-PKL7qzIh-1565187729654)(assets\1558765743472.png)]

​ 第四步,测试

[外链图片转存失败(img-Ntq14ZdV-1565187729656)(assets\1558765782821.png)]

[外链图片转存失败(img-GkqSeBd8-1565187729658)(assets\1558765981357.png)]

三、mybatis的注解开发(掌握)

xml版和注解版区别:

​ xml版:必须要有mybatis的核心配置文件sqlMapConfig.xml和sql映射文件xxMapper.xml(xxDao.xml)

注意:dao接口名称建议和实体类映射文件xxDao.xml文件名称一致

​ 注解版:必须要有mybatis的核心配置文件sqlMapConfig.xml。

​ 没有了sql映射文件xxMapper.xml(xxDao.xml)。

问题:

​ 使用注解版开发,只需要编写dao接口即可,至于实现的话,我们会采用注解形式在dao接口的方法之上实现。

​ 注解版开发一般在企业中为了适应springboot(微服务架构),因为微服务架构(写的少做的多)没有xml文件,在微服务架构中项目中只有一个配置文件.perperties

环境搭建:

核心配置文件sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!--配置别名-->
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>
    <!-- 配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定带有注解的dao接口所在位置 -->
    <mappers>
       <!-- <mapper class="com.itheima.dao.IUserDao"></mapper>-->
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

[外链图片转存失败(img-vdBMm7ln-1565187729661)(assets\1558767901669.png)]

注解版单表CRUD操作

查询操作:
 /**
     * 查询所有用户
     * @Select注解表示查询注解
     * @Select()括号中默认是value属性值,类型是String[]
     * 如果说value属性值只有一个,那么value可以省略不写,@Select("select * from user")
     * 但是如果value属性值是多个那么value不可以省略@Select(value={"select * from user","select * from user"})
     */
    @Select("select * from user")
    List<User> findAll();
新增操作:
/**
     * 保存用户
     * @param user
     * @Insert表示新增的注解
     * #{参数}必须要和当前接口方法中参数实体类中的相对应的属性名称一致
     */
    @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);
修改操作:
/**
     * 更新用户
     * @param user
     */
    @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
    void updateUser(User user);
删除操作:
 /**
     * 删除用户
     * @param userId
     */
    @Delete("delete from user where id=#{id} ")
    void deleteUser(Integer userId);
单一查询操作:
 /**
     * 根据id查询用户
     * @param userId
     * @return
     */
    @Select("select * from user  where id=#{id} ")
    User findById(Integer userId);
模糊查询操作:
   /**
     * 根据用户名称模糊查询
     * @param username
     * @return
     */
   @Select("select * from user where username like #{username} ")
    /*@Select("select * from user where username like '%${value}%' ")*/
    List<User> findUserByName(String username);
查询总数操作:
/**
     * 查询总用户数量
     * @return
     */
    @Select("select count(*) from user ")
    int findTotalUser();

注解版开发流程

注解版多表级联操作

分析:

​ 用户和账户关系:

​ 用户和账户可以作为一对多关系

​ 账户和用户可以作为多对一和一对一关系

演示一对一关系级联:

​ 查询账户,包含用户信息

第一步,在账户实体类中加入用户实体类作为属性存在

public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

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

第二步,编写IAccountDao接口

    /**
     * 查询所有账户,并且获取每个账户所属的用户信息
     * @return
     * property表示实体类中的属性名称
     * column表示实体类属性相对应的数据库表字段名称
     * one表示多对一(一对一)的级联关系配置
     *  one=@One(select="com.itheima.dao.IUserDao.findById",关联查询IUserDao接口中的findById得方法
     fetchType= FetchType.EAGER)表示立即加载
     */
    @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"),
            @Result(property = "user",column = "uid",
                    one=@One(select="com.itheima.dao.IUserDao.findById",
                            fetchType= FetchType.EAGER))
    })
    List<Account> findAll();

第三步,编写IUserDao接口中的findById方法

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

第四步,编写测试类

    @Test
    public  void  testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println("----每个账户的信息-----");
            System.out.println(account);
            System.out.println(account.getUser());
        }
    }

演示一对多关系级联:

​ 查询用户,包含账户信息

第一步,编写用户实体类信息

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接口

    /**
     * 查询所有用户
     * @return
     * 如果实体类中的属性名称和数据库表字段如果一致的话,那么 @Result可以省略
     *  many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
     *  表示一对多级联查询,
     *    fetchType = FetchType.LAZY加载方式为懒加载
     */
    @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();

第三步,编写IAccountDao接口中的findAccountByUid方法

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

第四步,测试

   @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());
        }*/
    }

总结:

​ 分析表与表之间的关联关系?

​ 用户表和账户表

[外链图片转存失败(img-PZNKiAa8-1565187729663)(assets/1559383613320.png)]

表关系分析:

如果说从用户表去查询账户表,在mybatis中称之为一对多(一个用户拥有多个账户)

如果说从账户表去查询用户表,在mybatis中称之为多对一(多个账户在同一个用户名下)或者一对一(一个账户在同一个用户下)操作

sql语句分析:

​ 查询账户,包含用户

​ 1.查询账户,select * from account(包含id,uid,money)

​ 2.包含用户,select * from user where id=uid (这个uid是account表中的外键)

​ 查询用户,包含账户

​ 1.查询用户,select * from user(包含id,username,birthday,sex,address)

​ 2.包含账户,select * from account where uid=id(这个id是user表中的主键)

​ mybatis的一级缓存?

​ sqlSession,代理对象由一级缓存产生,

​ 创建:加载核心配置文件的时候,打开opensession的时候,创建

​ 失效:close(),clearCache(),执行新增,修改,删除之后,一级缓存失效

​ mybatis注解一对一和一对多开发?

​ 1.一对一:查询账户,包含用户

​ [外链图片转存失败(img-wfnSdWPd-1565187729666)(assets/1559384634141.png)]

​ 2.一对多:查询用户,包含账户

​ [外链图片转存失败(img-CD93GO82-1565187729667)(assets/1559384998061.png)]

s中称之为多对一(多个账户在同一个用户名下)或者一对一(一个账户在同一个用户下)操作

sql语句分析:

​ 查询账户,包含用户

​ 1.查询账户,select * from account(包含id,uid,money)

​ 2.包含用户,select * from user where id=uid (这个uid是account表中的外键)

​ 查询用户,包含账户

​ 1.查询用户,select * from user(包含id,username,birthday,sex,address)

​ 2.包含账户,select * from account where uid=id(这个id是user表中的主键)

​ mybatis的一级缓存?

​ sqlSession,代理对象由一级缓存产生,

​ 创建:加载核心配置文件的时候,打开opensession的时候,创建

​ 失效:close(),clearCache(),执行新增,修改,删除之后,一级缓存失效

​ mybatis注解一对一和一对多开发?

​ 1.一对一:查询账户,包含用户

​ [外链图片转存中…(img-wfnSdWPd-1565187729666)]

​ 2.一对多:查询用户,包含账户

​ [外链图片转存中…(img-CD93GO82-1565187729667)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值