zoukankan      html  css  js  c++  java
  • mybatis高级

    一对一查询

    第一种,用拓展类的方式

    需要一对一查询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=".srcmainjava">
                <!-- 是否允许子包 -->
                <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=".srcmainjava">
                <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
                <property name="enableSubPackages" value="false" />
            </sqlMapGenerator>
    
            <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 -->
            <javaClientGenerator type="XMLMAPPER"
                                 targetPackage="com.zym.mapper" targetProject=".srcmainjava">
                <!-- 针对 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:developehcache" />

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

     

     

  • 相关阅读:
    Python 字符串格式化
    centos 7 & 6 优化脚本
    centos7.X 系统初始化>>优化
    重新嫁接rm命令
    ArcGIS Engine 10 开发常见问题的解决方法
    数据提交成功后如何避免alert被window.location.reload()影响
    服务器端IIS中部署带Office组件程序
    常用正则表达式
    C#解析XML
    使用Spire.Doc组件利用模板导出Word文档
  • 原文地址:https://www.cnblogs.com/taozizainali/p/11178183.html
Copyright © 2011-2022 走看看