zoukankan      html  css  js  c++  java
  • Mybatis的关联映射案例

    主要是对之前学习的关联映射做一个案例,自己动手实践一下,可以理解的更好一点。

    开发环境

    开发工具:idea
    Java环境: jdk1.8.0_121
    数据库:SQLServer
    项目结构,里面包含了三种关联映射的文件,会分别进行测试:

    完整的mybatis-config.xml文件,MybatisUtils工具类和db.properties文件

    <?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="db.properties"/>
    
            <settings>
                <!--打开延迟加载的开关-->
                <setting name="lazyLoadingEnabled" value="true"/>
                <!--将积极加载改为消息加载,即按需加载-->
                <setting name="aggressiveLazyLoading" value="false"/>
            </settings>
            <!--使用扫描包创建别名-->
            <typeAliases>
                <package name="com.ma.po"/>
            </typeAliases>
            <!--配置环境,默认的环境id为sqlserver-->
            <environments default="sqlserver">
                <!--配置id为sqlserver的数据库环境-->
                <environment id="sqlserver">
                    <!--使用JDBC的事务管理-->
                    <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>
            </environments>
            <!--配置mapper的位置-->
            <mappers>
                <mapper resource="com/ma/mapper/IdCardMapper.xml"/>
                <mapper resource="com/ma/mapper/PersonMapper.xml"/>
                <mapper resource="com/ma/mapper/UserMapper.xml"/>
                <mapper resource="com/ma/mapper/OrdersMapper.xml"/>
                <mapper resource="com/ma/mapper/ProductMapper.xml"/>
            </mappers>
        </configuration>
    
    public class MybatisUtils {
        private static SqlSessionFactory sqlSessionFactory = null;
        //初始化SqlSessionFactory对象
        static {
            try {
                //使用M主Batis提供的Resources类加载MyBatis的配置文件
                Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
                //构建SqlSessionFactory工厂
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取SqlSession对象的静态方法
         * @return
         */
        public static SqlSession getSession() {
            return sqlSessionFactory.openSession();
        }
    }
    
    jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
    jdbc.url=jdbc:sqlserver://localhost:1433;DatabaseName=mybatis
    jdbc.username=
    jdbc.password=
    

    一对一案例(模拟人和身份证的关系)

    1.创建两张数据表,tb_idcard和tb_person,并插入一些测试数据。

    create table tb_idcard(
                id int  identity(1,1) PRIMARY key,
                code varchar(18),            
    );
    insert into tb_idcard values ('321321199403012967');
    insert into tb_idcard values ('320321188505044526');
    create table tb_person(
                id int  identity(1,1) PRIMARY key,
                name varchar(32),
    	    age int,
    	    sex varchar(8),
    	    card_id int UNIQUE,
    	    FOREIGN KEY (card_id) REFERENCES tb_idcard(id)
    );
    insert into tb_person values ('Rose',29,'女',1);
    insert into tb_person values ('tom',26,'男',2);
    

    2.创建两个实体类:IdCard和Person

    /**
     * @author mz
     * @version V1.0
     * @Description: 证件持久化类
     * @create 2017-11-02 10:12
     */
    public class IdCard {
        private Integer id;
        private String code;
        //省略setter和getter方法
    }
    
    
    /**
     * @author mz
     * @version V1.0
     * @Description: 个人持久化类
     * @create 2017-11-02 10:13
     */
    public class Person {
        private Integer id;
        private String name;
        private Integer age;
        private String sex;
        private IdCard card;   //个人关联的证件
       //省略setter和getter方法
        }
    

    3.创建IdCardMapper.xml映射文件和PersonMapper.xml映射文件。
    IdCardMapper.xml映射文件

    <?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.ma.mapper.IdCardMapper">
    <!--根据id查询证件信息-->
    <select id="findCodeById" parameterType="Integer" resultType="IdCard">
        select * from tb_idcard where id = #{id}
    </select>
    </mapper>
    

    PersonMapper.xml映射文件

    <?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.ma.mapper.PersonMapper">
        <resultMap id="IdCardWithPersonResult" type="Person">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <!--一对一:association使用select属性引入别处一条语句-->
            <association property="card" column="card_id" javaType="IdCard"
                         select="com.ma.mapper.IdCardMapper.findCodeById"/>
        </resultMap>
        <!--嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
         <select id="findPersonById" parameterType="Integer" resultMap="IdCardWithPersonResult">
             select * from tb_person where id = #{id}
         </select>
    
        
        <resultMap id="IdCardWithPersonResult2" type="Person">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <association property="card" javaType="IdCard">
                <id property="id" column="card_id"/>
                <result property="code" column="code"/>
            </association>
        </resultMap>
        <!--嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集-->
        <select id="findPersonById2" parameterType="Integer" resultMap="IdCardWithPersonResult2">
            select p.*,c.code
            from tb_person p,tb_idcard c
            where p.card_id = c.id and p.id = #{id}
        </select>
    
    

    4.在测试类中添加测试方法

    /**
         * 嵌套查询
         */
        @Test
        public void findPersonByIdTest() {
            //获取SqlSession
            SqlSession sqlSession = MybatisUtils.getSession();
            //使用MyBatis嵌套查询的方式查询id为1的人的信息
            Person person = sqlSession.selectOne("com.ma.mapper.PersonMapper.findPersonById",1);
            //输出信息
            System.out.println(person);
            //关闭SqlSession
            sqlSession.close();
        }
        /**
         * 嵌套结果
         */
        @Test
        public void findPersonByIdTest2() {
            //获取SqlSession
            SqlSession sqlSession = MybatisUtils.getSession();
            //使用MyBatis嵌套查询的方式查询id为1的人的信息
            Person person = sqlSession.selectOne("com.ma.mapper.PersonMapper.findPersonById2",1);
            //输出信息
            System.out.println(person);
            //关闭SqlSession
            sqlSession.close();
        }
    

    5.分别运行findPersonByIdTest()和findPersonByIdTest2()的结果如下:


    从结果来看,嵌套查询要比嵌套结果多执行一条语句,结果是一样的。

    一对多案例(模拟用户与订单的关系)

    1.新建表tb_user和tb_orders

    create table tb_user(
                id int  identity(1,1) PRIMARY key,
                username varchar(32),
    	    address varchar(256)
                
    );
    insert into tb_user values ('詹姆斯','克利夫兰');
    insert into tb_user values ('科比','洛杉矶');
    insert into tb_user values ('保罗','洛杉矶');
    
    create table tb_orders(
                id int  identity(1,1) PRIMARY key,
                number varchar(32) not null,
    	    user_id int not null,
    	    FOREIGN KEY (user_id) REFERENCES tb_user(id)
    );
    insert into tb_orders values ('1000011','1');
    insert into tb_orders values ('1000012','2');
    insert into tb_orders values ('1000013','3');
    

    2.新建持久化类Orders和User。

    public class Orders {
        private Integer id;   //订单id
        private String number;//订单编号
        private List<Product> products;//关联商品集合信息
     //省略setter和getter方法
    }
    
    public class User {
        private Integer id;             //用户编号
        private String username;        //用户名
        private String address;         //用户地址
        private List<Orders> ordersList;//用户关联的订单
     //省略setter和getter方法
    }
    
    

    3.新建User|Mapper.xml文件

    <?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.ma.mapper.UserMapper">
        <resultMap id="UserWithOrdersResult" type="User">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="address" column="address"/>
            <!--一对多关联映射:collection ofType表示属性集合中元素的类型,List<Orders>属性即Orders类-->
            <collection property="ordersList" ofType="Orders">
                <id property="id" column="orders_id"/>
                <result property="number" column="number"/>
            </collection>
        </resultMap>
        <!--一对多:查看某一用户及其关联的订单信息,注意:当关联查询出的列名相同,则需要使用别名区分-->
        <select id="findUserWithOrders" parameterType="Integer" resultMap="UserWithOrdersResult">
            select u.*,o.id as orders_id, o.number
            from tb_user u, tb_orders o
            where u.id = o.user_id
            and u.id = #{id}
        </select>
    </mapper>
    

    4.添加测试代码:

    /**
         * 一对多
         */
        @Test
        public void findUserTest() {
            //获取SqlSession
            SqlSession sqlSession = MybatisUtils.getSession();
            //查询id为1的人的信息
            User user = sqlSession.selectOne("com.ma.mapper.UserMapper.findUserWithOrders",1);
            //输出信息
            System.out.println(user);
            //关闭SqlSession
            sqlSession.close();
        }
    

    5.测试结果:

    多对多(模拟订单和商品的关系)

    1.新建数据表tb_product和tb_ordersitem

    create table tb_product(
                id int  identity(1,1) PRIMARY key,
                name varchar(32),
                price float				
    );
    insert into tb_product values ('java','44.5');
    insert into tb_product values ('java web','38.5');
    insert into tb_product values ('ssm','50');
    
    create table tb_ordersitem(
                id int identity(1,1) PRIMARY key,
                orders_id int,
    	    product_id int,
                FOREIGN KEY (orders_id) REFERENCES tb_orders(id),
                FOREIGN KEY (product_id) REFERENCES tb_product(id)
    );
    insert into tb_ordersitem values ('1','1');
    insert into tb_ordersitem values ('1','3');
    insert into tb_ordersitem values ('3','3');
    

    2.创建Product持久化类

    public class Product {
        private Integer id;     //商品id
        private String name;    //商品名称
        private double price;   //商品单价
        private List<Orders> orders;//与订单的关联属性
     //省略setter和getter方法
    }
    

    3.创建OrdersMapper.xml和ProductMapper.xml的映射文件
    OrdersMapper.xml

    <?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.ma.mapper.OrdersMapper">
        <resultMap id="OrdersWithProductResult" type="Orders">
            <id property="id" column="id"/>
            <result property="number" column="number"/>
            <collection property="products" column="id" ofType="Product" select="com.ma.mapper.ProductMapper.findProductById">
    
            </collection>
        </resultMap>
    
        <!--多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型-->
        <select id="findOrdersWithProduct" parameterType="Integer" resultMap="OrdersWithProductResult">
            select * from tb_orders where id = #{id}
        </select>
    
        <resultMap id="OrdersWithProductResult2" type="Orders">
            <id property="id" column="id"/>
            <result property="number" column="number"/>
            <collection property="products" ofType="Product">
                <id property="id" column="pid"/>
                <result property="name" column="name"/>
                <result property="price" column="price"/>
    
            </collection>
        </resultMap>
        <select id="findOrdersWithProduct2" parameterType="Integer" resultMap="OrdersWithProductResult2">
            select o.*,p.id as pid,p.name,p.price
            from tb_orders o,tb_product p,tb_ordersitem oi
            where
                oi.orders_id = o.id and oi.product_id = p.id and o.id = #{id}
        </select>
    
    </mapper>
    

    ProductMapper.xml

    <?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.ma.mapper.ProductMapper">
        <select id="findProductById" parameterType="Integer" resultType="Product">
            select * from tb_product
            where
                id in(select product_id from tb_ordersitem where orders_id = #{id})
        </select>
    </mapper>
    

    4.添加测试代码

    /**
         * 多对多
         */
        @Test
        public void findOrdersTest() {
            //获取SqlSession
            SqlSession sqlSession = MybatisUtils.getSession();
            //查询id为1的订单中的商品的信息
            Orders orders = sqlSession.selectOne("com.ma.mapper.OrdersMapper.findOrdersWithProduct",1);
            //输出信息
            System.out.println(orders);
            //关闭SqlSession
            sqlSession.close();
        }
    
    
        /**
         * 多对多
         */
        @Test
        public void findOrdersTest2() {
            //获取SqlSession
            SqlSession sqlSession = MybatisUtils.getSession();
            //查询id为1的订单中的商品的信息
            Orders orders = sqlSession.selectOne("com.ma.mapper.OrdersMapper.findOrdersWithProduct2",1);
            //输出信息
            System.out.println(orders);
            //关闭SqlSession
            sqlSession.close();
        }
    

    5.分别运行findOrdersTest()和findOrdersTest2()的运行结果

    小结

    以上是对Mybatis对关联关系处理的一个实践,代码测试没有问题。

  • 相关阅读:
    Java并发编程原理与实战九:synchronized的原理与使用
    Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
    Java并发编程原理与实战七:线程带来的风险
    Java并发编程原理与实战六:主线程等待子线程解决方案
    Java并发编程原理与实战五:创建线程的多种方式
    Java并发编程原理与实战四:线程如何中断
    Java并发编程原理与实战三:多线程与多进程的联系以及上下文切换所导致资源浪费问题
    Java并发编程原理与实战二:并行&并发&多线程的理解
    ConcurrentHashMap 产生NullPointerException
    Java并发编程原理与实战一:聊聊并发
  • 原文地址:https://www.cnblogs.com/black-spike/p/7772416.html
Copyright © 2011-2022 走看看