zoukankan      html  css  js  c++  java
  • mybatis知识总结

    基于昨天的mybatis入门详解,今天我们再来看看mybatis稍微高深些的知识点.

    1.解决Model属性和数据库字段不一致的问题

      1),开启驼峰命名

      2),使用resultMap进行映射,

    <!-- 映射 -->
      <resultMap id="userMap" type="User">
        <result column="id" property="id" />
        <result column="user_name" property="userName" />
        <result column="name" property="name" />
        <result column="age" property="age" />
        <result column="sex" property="sex" />
        <result column="password" property="password" />
        
    </resultMap>
      <!--   这里使用的是resultMap,而不是resultType,
              id要保持一致;
      -->
    
        <select id="queryUserByUserName" resultMap="userMap">
            SELECT *, user_name userName  FROM tb_user WHERE user_name = #{userName}
        </select>
    
    
    <!--     <select id="queryUserByUserName" resultType="com.j1.jdbc.Model.User"> -->
    <!--         SELECT *, user_name userName  FROM tb_user WHERE user_name = #{userName} -->
    <!-hui-     </select> -->

    映射的初步应用就讲完了,接下来,我们看下mybatis的缓存机制,以及它与hibernate的区别(重要,面试会用到哦)

    缓存机制,在我的另一篇博客里有专门的博客介绍,在这里我再巩固一下.

    mybatis的缓存:

    一级缓存:

       作用域是session,当sqlSession.openSession()后开始执行,当参数,和sql语句相同时,会在控制台打印一条sql,再次执行的时候,或从缓存中命中,控制台不会再打印sql语句,当参数,sql,活着session关闭时,会重新打印一条新的sql语句.

    注意,在insert,update,delete时会刷新sql.

    原理:

    Mybatis执行查询时首先去缓存区命中,如果命中直接返回,没有命中则执行SQL,从数据库中查询。

    使用session.clearCache()强制查询不缓存。

    二级缓存:

        作用域是mapper的namespace,同一个namespace中查询sql可以从缓存中命中的,

    二级缓存是可以跨session的,在mapper.xml中加入<cache/>表示开启二级缓存.

    如何关闭二级缓存呢?

    默认是开启的;

    1.1.1.   二级缓存的高级配置

    至此,mybatis的缓存机制就讲完了,下面,我们来讨论一下,

    mybatis与hibernate的区别:

    第一方面:开发速度的对比

    就开发速度而言,Hibernate的真正掌握要比Mybatis来得难些。Mybatis框架相对简单很容易上手,但也相对简陋些。个人觉得要用好Mybatis还是首先要先理解好Hibernate。

    比起两者的开发速度,不仅仅要考虑到两者的特性及性能,更要根据项目需求去考虑究竟哪一个更适合项目开发,比如:一个项目中用到的复杂查询基本没有,就是简单的增删改查,这样选择hibernate效率就很快了,因为基本的sql语句已经被封装好了,根本不需要你去写sql语句,这就节省了大量的时间,但是对于一个大型项目,复杂语句较多,这样再去选择hibernate就不是一个太好的选择,选择mybatis就会加快许多,而且语句的管理也比较方便。

    第二方面:开发工作量的对比

    Hibernate和MyBatis都有相应的代码生成工具。可以生成简单基本的DAO层方法。针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。

    第三方面:sql优化方面

    Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。

    Hibernate HQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多人嫌弃因为太丑了。MyBatis的SQL是自己手动写的所以调整方便。但Hibernate具有自己的日志统计。Mybatis本身不带日志统计,使用Log4j进行日志记录。

    第四方面:对象管理的对比

    Hibernate 是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。也就是说,相对于常见的 JDBC/SQL 持久层方案中需要管理 SQL 语句,Hibernate采用了更自然的面向对象的视角来持久化 Java 应用中的数据。

    换句话说,使用 Hibernate 的开发者应该总是关注对象的状态(state),不必考虑 SQL 语句的执行。这部分细节已经由 Hibernate 掌管妥当,只有开发者在进行系统性能调优的时候才需要进行了解。而MyBatis在这一块没有文档说明,用户需要对对象自己进行详细的管理。
    第五方面:缓存机制

    Hibernate缓存

    Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。建议在一个Action操作中使用一个Session。一级缓存需要对Session进行严格管理。

    Hibernate二级缓存是SessionFactory级的缓存。 SessionFactory的缓存分为内置缓存和外置缓存。内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。

    MyBatis缓存

    MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。

    默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:  <cache/>

    字面上看就是这样。这个简单语句的效果如下:

    1. 映射语句文件中的所有 select 语句将会被缓存。
    2. 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
    3. 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
    4. 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
    5. 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
    6. 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

    所有的这些属性都可以通过缓存元素的属性来修改。

    比如: <cache  eviction=”FIFO”  flushInterval=”60000″  size=”512″  readOnly=”true”/>

    这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。可用的收回策略有, 默认的是 LRU:

    1. LRU – 最近最少使用的:移除最长时间不被使用的对象。
    2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

    flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

    size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是1024。

    readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。

    相同点:Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。

    不同点:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。

    MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。

    两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。

    而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。

    第六方面:总结

    对于总结,大家可以到各大java论坛去看一看

    相同点:Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。

    • Hibernate和MyBatis都支持JDBC和JTA事务处理。

    Mybatis优势

    • MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
    • MyBatis容易掌握,而Hibernate门槛较高。

    Hibernate优势

    • Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
    • Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
    • Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
    • Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

    他人总结

      • Hibernate功能强大,数据库无关性好,O/R映射能力强,如果你对Hibernate相当精通,而且对Hibernate进行了适当的封装,那么你的项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽。
      • Hibernate的缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate方面需要你的经验和能力都很强才行。
      • iBATIS入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的SQL使用经验,对于没有那么高的对象模型要求的项目来说,相当完美。
      • iBATIS的缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。

    mybatis的高级查询,为了能更好的说服问题,在此之前先贴上建表语句,

    /*
    Navicat MySQL Data Transfer
    
    Source Server         : 127.0.0.1
    Source Server Version : 50619
    Source Host           : 127.0.0.1:3306
    Source Database       : mybatis_test
    
    Target Server Type    : MYSQL
    Target Server Version : 50619
    File Encoding         : 65001
    
    Date: 2014-11-27 11:00:43
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for tb_item
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_item`;
    CREATE TABLE `tb_item` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `item_name` varchar(32) NOT NULL COMMENT '商品名称',
      `item_price` float(6,1) NOT NULL COMMENT '商品价格',
      `item_detail` text COMMENT '商品描述',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_item
    -- ----------------------------
    INSERT INTO `tb_item` VALUES ('1', 'iPhone 6', '5288.0', '苹果公司新发布的手机产品。');
    INSERT INTO `tb_item` VALUES ('2', 'iPhone 6 plus', '6288.0', '苹果公司发布的新大屏手机。');
    
    -- ----------------------------
    -- Table structure for tb_order
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_order`;
    CREATE TABLE `tb_order` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_id` bigint(20) NOT NULL,
      `order_number` varchar(20) NOT NULL COMMENT '订单号',
      PRIMARY KEY (`id`),
      KEY `FK_orders_1` (`user_id`),
      CONSTRAINT `FK_orders_1` FOREIGN KEY (`user_id`) REFERENCES `tb_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_order
    -- ----------------------------
    INSERT INTO `tb_order` VALUES ('1', '1', '20140921001');
    INSERT INTO `tb_order` VALUES ('2', '2', '20140921002');
    INSERT INTO `tb_order` VALUES ('3', '1', '20140921003');
    
    -- ----------------------------
    -- Table structure for tb_orderdetail
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_orderdetail`;
    CREATE TABLE `tb_orderdetail` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `order_id` int(32) DEFAULT NULL COMMENT '订单号',
      `item_id` int(32) DEFAULT NULL COMMENT '商品id',
      `total_price` double(20,0) DEFAULT NULL COMMENT '商品总价',
      `status` int(11) DEFAULT NULL COMMENT '状态',
      PRIMARY KEY (`id`),
      KEY `FK_orderdetail_1` (`order_id`),
      KEY `FK_orderdetail_2` (`item_id`),
      CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`order_id`) REFERENCES `tb_order` (`id`),
      CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`item_id`) REFERENCES `tb_item` (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_orderdetail
    -- ----------------------------
    INSERT INTO `tb_orderdetail` VALUES ('1', '1', '1', '5288', '1');
    INSERT INTO `tb_orderdetail` VALUES ('2', '1', '2', '6288', '1');
    INSERT INTO `tb_orderdetail` VALUES ('3', '2', '2', '6288', '1');
    INSERT INTO `tb_orderdetail` VALUES ('4', '3', '1', '5288', '1');
    
    -- ----------------------------
    -- Table structure for tb_user
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_user`;
    CREATE TABLE `tb_user` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `user_name` varchar(100) DEFAULT NULL COMMENT '用户名',
      `password` varchar(100) DEFAULT NULL COMMENT '密码',
      `name` varchar(100) DEFAULT NULL COMMENT '姓名',
      `age` int(10) DEFAULT NULL COMMENT '年龄',
      `sex` tinyint(1) DEFAULT NULL COMMENT '性别,1男性,2女性',
      `birthday` date DEFAULT NULL COMMENT '出生日期',
      `created` datetime DEFAULT NULL COMMENT '创建时间',
      `updated` datetime DEFAULT NULL COMMENT '更新时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `username` (`user_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_user
    -- ----------------------------
    INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '30', '1', '1984-08-08', '2014-09-19 16:56:04', '2014-09-21 11:24:59');
    INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '21', '2', '1991-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
    INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '22', '2', '1989-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
    INSERT INTO `tb_user` VALUES ('4', 'zhangwei', '123456', '张伟', '20', '1', '1988-09-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
    INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '李娜', '28', '1', '1985-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
    INSERT INTO `tb_user` VALUES ('6', 'lilei', '123456', '李磊', '23', '1', '1988-08-08', '2014-09-20 11:41:15', '2014-09-20 11:41:15');

     需求 根据订单编号查询订单信息和用户名,年龄,先分析这个需求,如图所示

    我们必须在去定义一个Model,去封装另外三个字段.(其实直接将多余的字段直接封装在Order中也是可以的)

    package com.j1.mybatis.mapper;
    
    import com.j1.mybatis.pojo.OrderUser;
    
    public interface OrderMapper {
        /**
         * 根据订单编号查询订单信息和用户名,年龄
         * @param orderNum
         * @return
         */
        public OrderUser querOrderAndUserByOrderNum(String orderNum);
    
    }
    package com.j1.mybatis.mapper;
    
    import static org.junit.Assert.*;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.j1.mybatis.pojo.OrderUser;
    
    public class OrderMapperTest {
        private OrderMapper orderMapper;
    
        @Before
        public void setUp() throws Exception {
            try {
                // 构造SqlSessionFactory
                // 定义配置文件路径
                String resource = "mybatis-config.xml";
                // 读取配置文件
                InputStream inputStream = Resources.getResourceAsStream(resource);
                // 通过SqlSessionFactoryBuilder构建一个SqlSessionFactory
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //            this.userDAO = new UserDao(sqlSessionFactory);
                SqlSession sqlSession = sqlSessionFactory.openSession(true);
                this.orderMapper=sqlSession.getMapper(OrderMapper.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    
        @Test
        public void testQuerOrderAndUserByOrderNum() {
            OrderUser orderUser=orderMapper.querOrderAndUserByOrderNum("20140921002");
            System.out.println(orderUser);
        }
    
    }
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.j1.mybatis.mapper.OrderMapper">
      
        <select id="querOrderAndUserByOrderNum" resultType="OrderUser">
                SELECT
                o.*,
                u.name,
                u.user_name,
                u.age
            FROM
                tb_order o
            LEFT JOIN tb_user u ON u.id = o.user_id
            WHERE
                o.order_number = #{orderNumber}
            
        </select>
        
    </mapper>
      
    <?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="jdbc.properties"/>
        <settings>
            <!-- 开启驼峰自动映射 -->
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        </settings>
        <typeAliases>
            <!-- 设置别名 -->
            <!-- <typeAlias type="com.j1.Model.User" alias="User"/> -->
            <package name="com.j1.mybatis.pojo"/>
        </typeAliases>
        <!-- 指定环境 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC" />
                <dataSource type="POOLED">
                    <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>
            <!-- 
            <environment id="test">
                <transactionManager type="JDBC" />
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.test.driver}" />
                    <property name="url" value="${jdbc.test.url}" />
                    <property name="username" value="${jdbc.test.username}" />
                    <property name="password" value="${jdbc.test.password}" />
                </dataSource>
            </environment>
             -->
        </environments>
        <mappers>
    <!--          <mapper resource="UserMapper.xml" />  -->
    <!--          <mapper resource="UserMapper2.xml" /> -->
    <!--          <mapper class="com.j1.dao.IUser"/>  -->
            <!-- 配置掃描包 -->
             <package name="com.j1.mybatis.mapper"/> 
        </mappers>
    </configuration>

    一对一的第二种查询:

    @Test
        public void testQuerOrderAndUserByOrderNum2() {
            Order order=orderMapper.querOrderAndUserByOrderNum("20140921002");
            System.out.println(order);
        }
    <!-- 一对一的第二种查询方法,进行映射 
    <resultMap id="orderMap" type="User">
        <result column="id" property="id" />
        <result column="user_name" property="userName" />
        <result column="name" property="name" />
        <result column="age" property="age" />
        <result column="sex" property="sex" />
        <result column="password" property="password" />
    </resultMap>
        -->
        
    <resultMap id="orderMap" type="Order" autoMapping="true">

    <!--
    property为Order的属性 user
    javaType为属性的java类型User
    -->
    <association property="user" javaType="User"></association> </resultMap> <select id="querOrderAndUserByOrderNum2" resultMap="orderMap"> SELECT o.*, u.name, u.user_name, u.age FROM tb_order o LEFT JOIN tb_user u ON u.id = o.user_id WHERE o.order_number = #{orderNumber} </select>

    一对多:

    这里需要注意的是,不能像一对一那样扩充一个对象了,因为在查询的结果来看,其实还是一个订单数据,只是,一个订单里面有两个订单详情书局而已,所以只能扩充一个List

    @Test
        public void queryOrderAndUserAndOrderDetailByOrderNumber() {
            Order order=orderMapper.queryOrderAndUserAndOrderDetailByOrderNumber("20140921002");
            System.out.println(order);
        }
    
    
    package com.j1.mybatis.mapper;
    
    import com.j1.mybatis.pojo.Order;
    import com.j1.mybatis.pojo.OrderUser;
    
    public interface OrderMapper {
        /**
         * 根据订单编号查询订单信息和用户名,年龄
         * @param orderNum
         * @return
         */
        public OrderUser querOrderAndUserByOrderNum(String orderNum);
        public Order querOrderAndUserByOrderNum2(String orderNum);
        public Order queryOrderAndUserAndOrderDetailByOrderNumber(String orderNum);
    
    }
    
    
    <!-- 一对多 -->
        <resultMap type="Order" id="orderAndUserAndOrderDetailResultMap" autoMapping="true" 
         extends="orderAndUserResultMap">
            <!-- 
                <id property="id" column="id"/>
                <association property="user" javaType="User" autoMapping="true"/> 
            -->
            
            <!-- 
                property: java对象中的属性名称
                javaType: 集合类型
                ofType: 集合中的元素的数据类型
             -->
            <collection property="orderdetails" javaType="List" ofType="Orderdetail" autoMapping="true">
                <id property="id" column="orderdetail_id"/>
                <!-- <result property="itemId" column="item_id"/> -->
            </collection>
        </resultMap>
        
        <select id="queryOrderAndUserAndOrderDetailByOrderNumber" resultMap="orderAndUserAndOrderDetailResultMap">
            SELECT
                o.*,
                u.name,
                u.user_name,
                u.age,
                od.id orderdetail_id,
              od.item_id
            FROM
                tb_order o
            LEFT JOIN tb_user u ON u.id = o.user_id
            LEFT JOIN tb_orderdetail od ON od.order_id = o.id
            WHERE
                o.order_number = #{orderNumber}
        </select>
    <resultMap type="Order" id="orderAndUserResultMap" autoMapping="true">
            <id property="id" column="id"/>
            
            <!-- 
                映射对象
                property : Order对象中的user属性名
                javaType :属性的java类型 
             -->
            <association property="user" javaType="User" autoMapping="true">
                <!-- 
                <result property="name" column="name"/>
                <result property="userName" column="user_name"/>
                <result property="age" column="age"/> 
                -->
            </association>
        </resultMap>
     

    多对多:

    <!-- 多对多 -->
        
        <resultMap type="Order" id="orderAndUserAndOrderDetailAndItemResultMap">
            <id property="id" column="id"/>
            <association property="user" javaType="User" autoMapping="true"/>
            
            <!-- 
                property: java对象中的属性名称
                javaType: 集合类型
                ofType: 集合中的元素的数据类型
             -->
            <collection property="orderdetails" javaType="List" ofType="Orderdetail" autoMapping="true">
                <id property="id" column="orderdetail_id"/>
                
                <!-- 完成 Item对象的映射 -->
                <association property="item" javaType="Item" autoMapping="true">
                    <id property="id" column="item_id"/>
                </association>
            </collection>
        </resultMap>
        <select id="queryOrderAndUserAndOrderDetailAndItemByOrderNumber" resultMap="orderAndUserAndOrderDetailAndItemResultMap">
            SELECT
                o.*,
                u.name,
                u.user_name,
                u.age,
                od.id orderdetail_id,
              od.item_id,
                i.item_detail,
                i.item_name,
                i.item_price
            FROM
                tb_order o
            LEFT JOIN tb_user u ON u.id = o.user_id
            LEFT JOIN tb_orderdetail od ON od.order_id = o.id
            LEFT JOIN tb_item i ON i.id = od.item_id
            WHERE
                o.order_number = #{orderNumber}
        </select>
      /**
           * 多对多
         * 查询订单,查询出下单人信息并且查询出订单详情中的商品数据。
         * 
         * @param orderNumber
         * @return
         */
        public Order queryOrderAndUserAndOrderDetailAndItemByOrderNumber(String orderNum);
     /**
         * 多对多
         */
        @Test
        public void testQueryOrderAndUserAndOrderDetailAndItemByOrderNumber() {
            Order order = this.orderMapper.queryOrderAndUserAndOrderDetailAndItemByOrderNumber("20140921001");
            System.out.println(order);
        }

    至此,mybatis的高级查询以及缓存机制就讲完了.代码亲测可行

  • 相关阅读:
    如何将asp.net MVC2项目升级为MVC3项目(微软官方自动升级工具:ASP.NET MVC 3 Application Upgrader )
    扩展Html Helper类,ASP.NET MVC框架提供了一个帮助我们构造Html元素的类:TagBuilder
    详解ASP.NET MVC2项目升级到MVC 3 RC
    NHibernate学习
    ASP.MVCNOTE
    MVC问题反馈页面代码
    Silverlightnote
    jqGrid
    必须掌握的八个DOS命令
    分页且带条件的存储过程
  • 原文地址:https://www.cnblogs.com/wangchuanfu/p/5888083.html
Copyright © 2011-2022 走看看