小夜埙
路很长,要耐心,慢慢走!

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

开发环境

开发工具: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对关联关系处理的一个实践,代码测试没有问题。

posted on 2017-11-03 20:34  小夜埙  阅读(732)  评论(0编辑  收藏  举报