MyBatis一对一,一对多,多对一关联查询

1、一对一关联查询的案例

(1)需求

 根据班级id查询班级信息(带老师信息)

(2)创建表和数据

 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关系。

CREATE TABLE teacher(  
    t_id INT PRIMARY KEY AUTO_INCREMENT,   
    t_name VARCHAR(20)  
);  
CREATE TABLE class(  
    c_id INT PRIMARY KEY AUTO_INCREMENT,   
    c_name VARCHAR(20),   
    teacher_id INT  
);  
ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);      
  
INSERT INTO teacher(t_name) VALUES('teacher1');  
INSERT INTO teacher(t_name) VALUES('teacher2');  
  
INSERT INTO class(c_name, teacher_id) VALUES('class_a', 1);  
INSERT INTO class(c_name, teacher_id) VALUES('class_b', 2);  

(3)构建实体

老师:

public class Teacher {  
  
    // 定义实体类的属性,与teacher表中的字段对应  
    private int id; // id===>t_id  
    private String name; // name===>t_name  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public String toString() {  
        return "Teacher [id=" + id + ", name=" + name + "]";  
    }  
}  

班级:

public class Classes {  
  
    // 定义实体类的属性,与class表中的字段对应  
    private int id; // id===>c_id  
    private String name; // name===>c_name  
  
    /** 
     * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性, 
     * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的 
     */  
    private Teacher teacher;  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public Teacher getTeacher() {  
        return teacher;  
    }  
  
    public void setTeacher(Teacher teacher) {  
        this.teacher = teacher;  
    }  
  
    @Override  
    public String toString() {  
        return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher  
                + "]";  
    }  
}  

(4)定义Mapper对象

public interface ClassMapper {  
    /** 
     * 用于测试,非懒加载的one2one的实现 
     *  
     * @param id 
     * @return 
     */  
    public Classes getClass1(int id);  
  
    /** 
     * 用于测试,懒加载的one2one的实现 
     *  
     * @param id 
     * @return 
     */  
    public Classes getClass2(int id);  
}  

(5)定义sql映射文件classMapper.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.baowei.mapper.ClassMapper">  
  
    <!--   
                 根据班级id查询班级信息(带老师的信息)  
         ##1. 联表查询(非懒加载的实现)  
         SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;  
           
         ##2. 执行两次查询(懒加载的实现)  
         SELECT * FROM class WHERE c_id=1;  //teacher_id=1  
         SELECT * FROM teacher WHERE t_id=1;//使用上面得到的teacher_id  
    -->  
  
     <!--   
                       方式一:(非懒加载的实现)  
                                     嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集  
                                     封装联表查询的数据(去除重复的数据)  
             select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1  
     -->  
    <select id="getClass1" parameterType="int" resultMap="ClassResultMap">  
        select *  
        from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}  
    </select>  
    <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->  
    <resultMap type="com.baowei.entity.Classes" id="ClassResultMap">  
        <id property="id" column="c_id" />  
        <result property="name" column="c_name" />  
        <association property="teacher" javaType="com.baowei.entity.Teacher">  
            <id property="id" column="t_id" />  
            <result property="name" column="t_name" />  
        </association>  
    </resultMap>  
  
    <!--   
                  方式二:(懒加载的实现)  
                           嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型  
         SELECT * FROM class WHERE c_id=1;  
         SELECT * FROM teacher WHERE t_id=1   //1 是上一个查询得到的teacher_id的值  
     -->  
    <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">  
        select *  
        from class where c_id=#{id}  
    </select>  
    <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->  
    <resultMap type="com.baowei.entity.Classes" id="ClassResultMap2">  
        <id property="id" column="c_id" />  
        <result property="name" column="c_name" />  
        <association property="teacher" column="teacher_id"  
            select="getTeacher" />  
    </resultMap>  
    <select id="getTeacher" parameterType="int"  
        resultType="com.baowei.entity.Teacher">  
        SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}  
    </select>  
  
</mapper> 

(6)SqlMapConfig.xml配置

<?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>  
    <!--数据库的连接配置 -->  
    <environments default="development">  
        <environment id="development">  
            <!-- 使用jdbc事务管理,事务控制由mybatis -->  
            <transactionManager type="JDBC" />  
            <!-- 数据库连接池,由mybatis管理 -->  
            <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>  
    <!-- 加载 映射文件 -->  
    <mappers>  
        <package name="com.baowei.mapper" />  
    </mappers>  
  
</configuration> 

(7).MyBatisUtil.java工具

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;  
  
public class MyBatisUtil {  
  
    /** 
     * 获取SqlSessionFactory 
     *  
     * @return SqlSessionFactory 
     */  
    public static SqlSessionFactory getSqlSessionFactory() {  
        String resource = "SqlMapConfig.xml";  
        InputStream inputStream = null;  
        SqlSessionFactory sqlSessionFactory = null;  
        try {  
            inputStream = Resources.getResourceAsStream(resource);  
            sqlSessionFactory = new SqlSessionFactoryBuilder()  
                    .build(inputStream);  
  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return sqlSessionFactory;  
    }  
  
    /** 
     * 获取SqlSession 
     *  
     * @return SqlSession 
     */  
    public static SqlSession getSqlSession() {  
        return getSqlSessionFactory().openSession();  
    }  
  
    /** 
     * 获取SqlSession 
     *  
     * @param isAutoCommit 
     *            true 表示创建的SqlSession对象在执行完SQL之后会自动提交事务 false 
     *            表示创建的SqlSession对象在执行完SQL之后不会自动提交事务 
     *            ,这时就需要我们手动调用sqlSession.commit()提交事务 
     * @return SqlSession 
     */  
    public static SqlSession getSqlSession(boolean isAutoCommit) {  
        return getSqlSessionFactory().openSession(isAutoCommit);  
    }  
  
    public static void main(String[] args) {  
        System.out.println(getSqlSessionFactory());  
    }  
}  

(8)测试代码

import org.apache.ibatis.session.SqlSession;  
import org.junit.Test;  
  
import com.baowei.entity.Classes;  
import com.baowei.mapper.ClassMapper;  
import com.baowei.utils.MyBatisUtil;  
  
public class TestOne2One {  
  
    /** 
     * 非懒加载的one2one的测试 
     */  
    @Test  
    public void testGetClass() {  
        SqlSession sqlSession = MyBatisUtil.getSqlSession();  
  
        ClassMapper mapper = sqlSession.getMapper(ClassMapper.class);  
        Classes clazz = mapper.getClass1(1);  
  
        // 使用SqlSession执行完SQL之后需要关闭SqlSession  
        sqlSession.close();  
        System.out.println(clazz.getId());  
    }  
  
    /** 
     * 懒加载的one2one的测试 
     */  
    @Test  
    public void testGetClass2() {  
        SqlSession sqlSession = MyBatisUtil.getSqlSession();  
  
        ClassMapper mapper = sqlSession.getMapper(ClassMapper.class);  
        Classes clazz = mapper.getClass2(1);  
  
        // 使用SqlSession执行完SQL之后需要关闭SqlSession  
        sqlSession.close();  
        System.out.println(clazz.getId());  
        // 可用于测试懒加载(查看日志的sql输出结果,就可以发现使用了懒加载)  
        //System.out.println(clazz.getTeacher());  
  
    }  
}  

2.一对多/多对一查询案例

(1)需求

本实例使用顾客和订单的例子做说明: 一个顾客可以有多个订单, 一个订单只对应一个顾客。

(2)创建表和数据

CREATE DATABASE test;    
  
USE test;  
  
CREATE TABLE person(  
  personId VARCHAR(36) PRIMARY KEY,  
  personName VARCHAR(64),  
  personAddress VARCHAR(128),  
  personTel VARCHAR(11)  
);  
  
CREATE TABLE orders(  
  orderId VARCHAR(36) PRIMARY KEY,  
  orderNumber VARCHAR(20),  
  orderPrice INT,  
  pid VARCHAR(36)  
);  
  
INSERT INTO person VALUES('001', 'Jack', 'Wuhan', '1234567');  
INSERT INTO orders VALUES('O_00001', '00001', 100, '001');  
INSERT INTO orders VALUES('O_00002', '00002', 200, '001');  
  
SELECT p.*, o.*  
FROM person p   
  JOIN orders o ON (p.personId=o.pid)  
WHERE p.personId = '001' 

(3)构建实体

客户:

public class Person {  
  
    private String id;  
    private String name;  
    private String address;  
    private String tel;  
      
    private List<Order> orders;  
      
    @Override  
    public String toString() {  
        return "{id: " + id + ", name: " + name + ", address: " + address + ", tel: " + tel + "}";  
    }  
}  

订单:

public class Order {  
  
    private String id;  
    private String number;  
    private int price;  
      
    private Person person;   
      
    @Override  
    public String toString() {  
        return "{id: " + id + ", number: " + number + ", price: " + price + "}";  
    }  
  
}  

(4)一对多实体配置: Person.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.zdp.domain.Person">  
  
    <resultMap type="Person" id="personBean">  
        <id column="personId" property="id"/>  
        <result column="personName" property="name"/>  
        <result column="personAddress" property="address"/>  
        <result column="personTel" property="tel"/>  
          
        <!-- 一对多的关系 -->  
        <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->  
        <collection property="orders" ofType="Order">  
            <id column="orderId" property="id"/>  
            <result column="orderNumber" property="number"/>  
            <result column="orderPrice" property="price"/>  
        </collection>  
    </resultMap>  
      
    <!-- 根据id查询Person, 关联将Orders查询出来 -->  
    <select id="selectPersonById" parameterType="string" resultMap="personBean">  
        select p.*, o.* from person p, orders o where p.personId  = o.pid and p.personId = #{id}  
    </select>  
      
</mapper>  

 (5)多对一实体配置:order.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.zdp.domain.Order">  
    <resultMap type="Order" id="orderBean">  
        <id column="orderId" property="id"/>  
        <result column="orderNumber" property="number"/>  
        <result column="orderPrice" property="price"/>  
          
        <!-- 多对一的关系 -->  
        <!-- property: 指的是属性的值, javaType:指的是属性的类型-->  
        <association property="person" javaType="Person">  
            <id column="personId" property="id"/>  
            <result column="personName" property="name"/>  
            <result column="personAddress" property="address"/>  
            <result column="personTel" property="tel"/>  
        </association>  
    </resultMap>  
      
    <!-- 根据id查询Order, 关联将Person查询出来 -->  
    <select id="selectOrderById" parameterType="string" resultMap="orderBean">  
        select p.*, o.* from person p, orders o where p.personId  = o.pid and o.orderId = #{id}  
    </select>  
      
</mapper> 

(6)SqlMapConfig.xml配置

<?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>  
    <typeAliases>  
        <typeAlias type="com.zdp.domain.Person" alias="Person"/>    
        <typeAlias type="com.zdp.domain.Order" alias="Order"/>    
    </typeAliases>  
    <environments default="development">  
        <environment id="development">  
            <transactionManager type="JDBC" />  
            <dataSource type="POOLED">  
                <property name="driver" value="com.mysql.jdbc.Driver" />  
                <property name="url" value="jdbc:mysql://localhost/test" />  
                <property name="username" value="root" />  
                <property name="password" value="root" />  
            </dataSource>  
        </environment>  
    </environments>  
    <mappers>  
        <!-- 映射文件的位置 -->  
        <mapper resource="com/zdp/domain/Person.xml" />  
        <mapper resource="com/zdp/domain/Order.xml" />  
    </mappers>  
</configuration> 

(7)测试代码

/** 
 * 测试一对多和多对一 
 */  
public class MybatisTest {  
  
    private SqlSessionFactory ssf;   
  
    @Before  
    public void initSF() throws Exception {  
        String resource = "sqlMapConfig.xml";  
        InputStream inputStream = Resources.getResourceAsStream(resource);  
        ssf = new SqlSessionFactoryBuilder().build(inputStream);  
    }  
  
    @Test//一对多关联查询  
    public void selectPersonById()throws Exception{  
        SqlSession session = ssf.openSession();  
        Person person = session.selectOne("com.zdp.domain.Person.selectPersonById", "001");  
        System.out.println(person.getOrders());  
    }  
      
    @Test//多对一关联查询  
    public void selectOrderById()throws Exception{  
        SqlSession session = ssf.openSession();  
        Order order = session.selectOne("com.zdp.domain.Order.selectOrderById", "O_00001");  
        System.out.println(order.getPerson().getName());  
    }  
}  

3.参考博文

(1)http://www.cnblogs.com/xdp-gacl/p/4264440.html

(2)http://blog.csdn.net/jkxiaoxing/article/details/52199386

猜你喜欢

转载自blog.csdn.net/u014267900/article/details/79514053