一对一查询

第一种,用拓展类的方式

需要一对一查询Course和Teacher两个表

新建一个类,继承Course类,然后将Teacher类中的属性加到这个新类中,还需要有get和set方法

之后用debug查看

package com.zym.pojo;

public class ct extends Course{

//    private String t_id;
    private String t_name;

//    @Override
////    public String getT_id() {
////        return t_id;
////    }
//
//    @Override
//    public void setT_id(String t_id) {
//        this.t_id = t_id;
//    }

    public String getT_name() {
        return t_name;
    }

    public void setT_name(String t_name) {
        this.t_name = t_name;
    }
}

第二种使用resultMap

使用resultMap,定义专门的resultMap用于映射一对一查询结果。

在一个类中,添加另一个类的对象属性,并设置get set方法

public class Teacher {

    private String t_id;
    private String t_name;
    private Course Course;

    public Course getCourse() {
        return Course;
    }

    public void setCourse_obj(Course course_obj) {
        Course = course_obj;
    }

xml

   <resultMap id="Teacher_map" type="Teacher">
        <id property="t_id" column="t_id"/>
        <result property="t_name" column="t_name"/>

        <association property="Course" javaType="Course">
            <id property="t_id" column="t_id"/>
            <result property="c_name" column="c_name"/>
            <result property="c_id" column="c_id"/>
        </association>
    </resultMap>

    <select id="select_onebyone_map" resultMap="Teacher_map">

      SELECT  c_name,t_name,c.c_id,t.t_id,c.t_id FROM Course c
         LEFT JOIN Teacher t on c.t_id=t.t_id;


    </select>

一对多

student和score的一对多

public class Student {
    private Integer s_id;
    private String s_name;
    private Date s_birth;
    private String s_sex;

    private List<Score> Scores;

    public List<com.zym.pojo.Score> getScore() {
        return Scores;
    }

    public void setScore(List<com.zym.pojo.Score> score) {
        Scores = score;
    }

xml

    <resultMap id="stu_score_map" type="Student">
        <id property="s_id" column="s_id"/>
        <result property="s_name" column="s_name"/>
        <result property="s_birth" column="s_birth"/>
        <result property="s_sex" column="s_sex"/>
        <collection property="Scores" javaType="List" ofType="Score">
            <id  property="s_id" column="s_id_2"/>
            <result property="s_score" column="s_score"/>
            <result property="c_id" column="c_id"/>
        </collection>

    </resultMap>

    <select id="select_ones_score" resultMap="stu_score_map">
   SELECT s_name,stu.s_id,sco.s_id as sco_s_id,s_sex,s_score FROM
Student stu  LEFT JOIN Score  sco on
stu.s_id=sco.s_id

    </select>

多对多关系

public class Goods {
    private Integer id;
    private String gname;
    private Double price;
    private String gtype;
    //多对多
    private List<Order> order;
    
public class Order implements Serializable{
    private Integer id;
    private Integer userId;
    private Integer number;
    private Date createtime;
    private String note;
    // 一对一
    private User user;
    // 多对多
    private List<Goods> listgoods;

xml

<mapper namespace="com.jy.mapper.UserMapper">
    <!-- mang2mang 订单和商品信息 -->
    <resultMap type="Order" id="orderandgoodsmap">
        <!-- 主键映射关系 -->
        <id property="id" column="oid"/>/映射中间表
        <result property="createtime" column="createtime"/>
        <result property="number" column="number"/>
        <collection property="listgoods" javaType="list" ofType="goods">
            <!-- 主键映射关系 -->
        <id property="id" column="gid"/>  /映射中间表
        <result property="gname" column="gname"/>
        <result property="gtype" column="gtype"/>
        </collection>
    </resultMap>
    <select id="selectOrderAndGoods" resultMap="orderandgoodsmap">
        select o.id oid,o.createtime,o.number,g.id gid,g.gname,g.gtype
        from t_goods g,t_order o,order_goods og
        where g.id=og.gid and o.id=og.oid
    </select>

 使用mybatis插件进行自动生成关系

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--导入属性配置-->
    <properties resource="jdbc.properties"></properties>
    <!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
    <!--<classPathEntry location="${db.driverLocation}" />-->

    <!-- context 是逆向工程的主要配置信息 -->
    <!-- id:起个名字 -->
    <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 -->
    <context id="default" targetRuntime="MyBatis3">

        <!--optional,旨在创建class时,对注释进行控制-->
        <commentGenerator>
            <property name="suppressDate" value="true" />
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--jdbc的数据库连接-->
        <jdbcConnection driverClass="${db.driverClassName}"
                        connectionURL="${db.url}"
                        userId="${db.username}"
                        password="${db.password}">
        </jdbcConnection>

        <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 -->
            <!-- 不是 doublelong 类型 -->
            <!-- 使用常用的基本类型代替 sql 包下的引用类型 -->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetPackage:生成的实体类所在的包 -->
        <!-- targetProject:生成的实体类所在的硬盘位置 -->
        <javaModelGenerator targetPackage="com.zym.pojo"
                            targetProject=".\src\main\java">
            <!-- 是否允许子包 -->
            <property name="enableSubPackages" value="false" />
            <!-- 是否对modal添加构造函数 -->
            <property name="constructorBased" value="true" />
            <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
            <property name="trimStrings" value="true" />
            <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
            <property name="immutable" value="false" />
        </javaModelGenerator>

        <!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 -->
        <sqlMapGenerator targetPackage="com.zym.mapper"
                         targetProject=".\src\main\java">
            <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.zym.mapper" targetProject=".\src\main\java">
            <!-- 针对 oracle 数据库的一个配置,是否把 schema 作为字包名 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <table tableName="user" >

               <!--enableCountByExample="false" enableUpdateByExample="false"-->
               <!--enableDeleteByExample="false" enableSelectByExample="false"-->
               <!--selectByExampleQueryId="false">-->
        </table>

        <table tableName="Student"></table>
        <table tableName="Score"></table>
        <table tableName="Teacher"></table>
    </context>

</generatorConfiguration>

之后直接在运行插件,但是这个值对应生成一张表的查询,无法解决一对一,一对多,和多对多关系。

使用方法:

    public void  mybatis_plugin_test() throws IOException {
        init();
        SqlSession sqlSession = this.sqlSessionFactory.openSession();
        Object mapper = sqlSession.getMapper(StudentMapper.class);


        List<Student> students = ((StudentMapper) mapper).selectByExample(null);
        System.out.println(students.size());

        StudentExample st = new StudentExample();
//        st.createCriteria().andSNameLike("%李%");
//        List<Student> studentList = ((StudentMapper) mapper).selectByExample(st);
//        System.out.println(studentList);
        st.createCriteria().andSIdEqualTo("01");//支持链式操作
        List<Student> students1 = ((StudentMapper) mapper).selectByExample(st);
        System.out.println(students1);

    }


}

什么是查询缓存

Mybatis的一级缓存

是指SqlSession。一级缓存的作用域是一个SqlSession。Mybatis默认开启一级缓存。

在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则SqlSession的缓存清空。

Mybatis的二级缓存

是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。(二级缓存是SqlSessionFactory级别的缓存)

在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。

 

二级存使用范围:如果项目中的表数据允许出现少量的冗余数据,或者是只读数据;可以把这些数据放到二级缓存;

一级缓存原理

一级缓存区域是根据SqlSession为单位划分的。

每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。

 SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。

  二级缓存原理

 二级缓存是mapper级别的。Mybatis默认是没有开启二级缓存。

 第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。

第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

开启二级缓存

1、  在核心配置文件SqlMapConfig.xml中加入以下内容(开启二级缓存总开关):

cacheEnabled设置为 true

 2、在映射文件中,加入以下内容,开启二级缓存:

<!-- 开启二级缓存 -->

    <!-- 单位:毫秒 -->

    <cache type="org.mybatis.caches.ehcache.EhcacheCache">

       <property name="timeToIdleSeconds" value="12000"/>

        <property name="timeToLiveSeconds" value="3600"/>

        <!-- 同ehcache参数maxElementsInMemory -->

       <property name="maxEntriesLocalHeap" value="1000"/>

       <!-- 同ehcache参数maxElementsOnDisk -->

        <property name="maxEntriesLocalDisk" value="10000000"/>

        <property name="memoryStoreEvictionPolicy" value="LRU"/>

    </cache> 

实现序列化

由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。

如果该类存在父类,那么父类也要实现序列化。

禁用二级缓存

该statement中设置userCache=false可以禁用当前select语句的二级缓存,即每次查询都是去数据库中查询,默认情况下是true,即该statement使用二级缓存。

ehcache.xml

 

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <!--diskStore:缓存数据持久化的目录 地址  -->

    <diskStore path="E:\develop\ehcache" />

    <defaultCache

       maxElementsInMemory="1000"

       maxElementsOnDisk="10000000"

       eternal="false"

       overflowToDisk="false"

       diskPersistent="true"

       timeToIdleSeconds="120"

       timeToLiveSeconds="120"

       diskExpiryThreadIntervalSeconds="120"

       memoryStoreEvictionPolicy="LRU">

    </defaultCache>

</ehcache>

懒加载

resultMap中的association和collection标签具有延迟加载的功能。

延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。使用关联信息时再去加载关联信息。

设置延迟加载

立即加载

需要在SqlMapConfig.xml文件中,在<settings>标签中设置下延迟加载。

lazyLoadingEnabled、aggressiveLazyLoading

设置项

描述

允许值

默认值

lazyLoadingEnabled

全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。

true | false

false

aggressiveLazyLoading

当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。

true | false

true

 

1

2

3

4

5

6

7

8

9

10

<!-- 开启延迟加载 -->

    <settings>

        <!-- lazyLoadingEnabled:延迟加载启动,默认是false -->

        <setting name="lazyLoadingEnabled" value="true"/>

        <!-- aggressiveLazyLoading:积极的懒加载,false的话按需加载,默认是true -->

        <setting name="aggressiveLazyLoading" value="false"/>

         

        <!-- 开启二级缓存,默认是false -->

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

    </settings>

 

 <!—延迟加载 -->

    <select id="selectOrderById" resultMap="ordrermap">

       select * from orders

    </select>

    <resultMap type="order" id="ordrermap">

       <id property="id" column="id"/>

       <result property="number" column="number"/>

       <association property="user" javaType="user" column="user_id" select="selectUseByUserid">

          

       </association>

    </resultMap>

    <select id="selectUseByUserid" resultType="user">

       select * from t_user where id=#{id}

    </select>

 

 

 

 

 

 

 

 

 

 

 

posted on 2019-07-12 20:11  睡觉的阿狸  阅读(242)  评论(0编辑  收藏  举报