想要了解MyBatis基础的朋友可以通过传送门:

  MyBatis学习(一)---配置文件,Mapper接口和动态SQL http://www.cnblogs.com/ghq120/p/8322302.html

  本文主要介绍了用MyBatis实现数据表之间的各种关系,例如一对多,多对一,一对一和多对多。

一对多和多对一

本项目的例子为公司的部门和员工之间的关系,即一个部门对应多个员工,反过来多个员工对应一个部门即为多对一。

项目的目录为

本项目依旧使用Oracle数据库,对应的表为employee和department

employee表的列

department

表对应的实体类分别为

Employee.java

package com.ghq.model.entity;

public class Employee {
private Integer id;
private String empName;
private Department dept;
public Employee(Integer id, String empName, Department dept) {
super();
this.id = id;
this.empName = empName;
this.dept = dept;
}
public Employee(String empName, Department dept) {
super();
this.empName = empName;
this.dept = dept;
}
public Employee() { }
//此处省略setter/getter方法
@Override
public String toString() {
return "Employee [id=" + id + ", empName=" + empName + ", dept=" + dept
+ "]";
} }

Department.java

package com.ghq.model.entity;

import java.util.List;

public class Department {
private Integer id;
private String deptname;
//部门下所有员工
private List<Employee> emps;
public Department(Integer id, String deptname, List<Employee> emps) {
super();
this.id = id;
this.deptname = deptname;
this.emps = emps;
}
public Department(String deptname, List<Employee> emps) {
super();
this.deptname = deptname;
this.emps = emps;
}
public Department() { }
//此处省略setter/getter方法
@Override
public String toString() {
return "Department [id=" + id + ", deptname=" + deptname + ", emps="
+ emps + "]";
} }

配置文件仍为mybatis-config.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>
<!-- 加载db.properties文件 -->
<properties resource="db.properties"></properties> <!-- 在配置文件中定义别名,可以在映射文件中使用别名 -->
<typeAliases>
<!-- 为该包下的实体类定义别名 -->
<package name="com.ghq.model.entity"/>
</typeAliases> <!-- 指定了默认的环境为development -->
<environments default="development">
<!-- 指出了环境的唯一标识 -->
<environment id="development">
<!-- 指出了事务管理器 -->
<transactionManager type="JDBC"/>
<!-- 指出了连接池,并指出了连接数据库的驱动,url,用户名,密码 -->
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册映射文件 -->
<mappers>
<package name="com.ghq.model.dao"/>
</mappers>
</configuration>

db.properties文件中

db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
db.username=scott
db.password=itcast

工具类下MybatisDb.java获取获取SqlSessionFactory以及SqlSession的对象,SqlSession中具有对数据表增删改查的方法

package com.ghq.model.utils;

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 MybatisDb {
private static String config = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFac; static{
try {
//读取配置文件
InputStream inputstream = Resources.getResourceAsStream(config);
//获取SqlSessionFactory对象
sqlSessionFac = new SqlSessionFactoryBuilder().build(inputstream);
} catch (IOException e) {
e.printStackTrace();
}
} //获取SqlSession对象,并且开启了事务
public static SqlSession getSession(){
return sqlSessionFac.openSession();
} }

dao组件

DeptDao主要是获取指定部门下的员工信息

public interface DeptDao {
//获取部门下员工信息(部门信息和员工信息)
public List<Department> getDeptEmployee();
}

EmpDao是获取每个员工的部门信息

public interface EmpDao {
//获取每个员工的部门信息
public List<Employee> getEmployeeDept();
}

  Department中获取所有的员工的属性时集合类型的,在配置文件中使用的元素是<collection>,该元素必须添加property和ofType属性, property指出集合属性名,ofType指出集合元素的类型

  Employee中员工对应的部门信息是实体类类型,在配置文件中使用<association>元素,该元素必须指定property和javaType,property指出的是实体的属性名,javaType指出了该属性的类型

DeptDao的配置文件为DeptDao.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.ghq.model.dao.DeptDao">
<resultMap type="Department" id="deptMap">
<id column="did" property="id"/>
<result column="deptname" property="deptname"/> <!-- 映射集合使用的元素是Collection,该元素必须添加property和ofType属性,
property指出集合属性名,ofType指出集合元素的类型 -->
<collection property="emps" ofType="Employee">
<id column="eid" property="id"/>
<result column="empname" property="empName"/>
</collection>
</resultMap> <select id="getDeptEmployee" resultMap="deptMap">
SELECT d.id did, d.deptname, e.id eid, e.empname
    FROM department d LEFT JOIN employee e
    ON d.id = e.deptid
</select> </mapper>

EmpDao的配置文件为EmpDao.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.ghq.model.dao.EmpDao"> <!-- 用于完成查询出的列名和相应实体属性的映射 -->
<resultMap type="Employee" id="empMap">
<!-- 用于映射主键列 -->
<id column="eid" property="id"/>
<!-- 用于映射普通列 -->
<result column="empname" property="empName"/> <!-- association元素必须指定property和javaType,property指出的是实体的属性名,javaType指出了该属性的类型 -->
<association property="dept" javaType="Department">
<id column="did" property="id"/>
<result column="deptname" property="deptname"/>
</association>
</resultMap> <!-- 查询出的列名和实体的属性名不一致,所以应该使用resultMap -->
<select id="getEmployeeDept" resultMap="empMap">
SELECT e.id eid, e.empname, d.id did, d.deptname
    FROM employee e LEFT JOIN department d
    ON d.id = e.deptid
</select> </mapper>

使用单元测试

public class testmybatis {

    //此方法对应DeptDao,为测试获取部门下所有员工的方法
@Test
public void testgetDeptEmployee(){
SqlSession session = MybatisDb.getSession();
DeptDao deptDao = session.getMapper(DeptDao.class);
List<Department> depts = deptDao.getDeptEmployee();
session.close();
if (depts != null && depts.size() > 0) {
for (Department d : depts) {
List<Employee> emps = d.getEmps();
if (emps !=null && emps.size() > 0) {
for (Employee e : emps) {
System.out.println(d.getId()+" "+d.getDeptname()+" "+e.getId()+" "+e.getEmpName());
}
} else{
System.out.println(d.getId()+" "+d.getDeptname()+" "+null+" "+null);
}
}
}else {
System.out.println("沒有部门");
} }
}

//此方法对应EmpDao,为测试员工对应部门的方法
@Test
public void testgetEmployeeDept(){
SqlSession session = MybatisDb.getSession();
EmpDao empDao = session.getMapper(EmpDao.class);
List<Employee> emps = empDao.getEmployeeDept();
session.close();
if (emps != null && emps.size() > 0) {
for (Employee e : emps) {
if (e.getDept() == null) {
System.out.println(e.getId()+" "+e.getEmpName()+" "+"没有部门");
}else{
System.out.println(e.getId()+" "+e.getEmpName()+" "+e.getDept().getId()+" "+e.getDept().getDeptname());
}
} } }

一对一

  本项目为公民和身份证之间的关系,即一个公民对应一张身份证

对应的表分别为citi_tb和card_tb

citi_tb

card_tb

表对应的实体类分别为

Citi.java

package com.ghq.model.entity;

public class Citi {
private Integer id;
private String citiName;
private IdCard card;
public Citi(Integer id, String citiName, IdCard card) {
super();
this.id = id;
this.citiName = citiName;
this.card = card;
}
public Citi(String citiName, IdCard card) {
super();
this.citiName = citiName;
this.card = card;
}
public Citi() { }
//此处省略setter/getter方法

 

IdCard.java

package com.ghq.model.entity;

public class IdCard {
private Integer id;
private String cardNo;
private String address;
private Citi citi;
public IdCard(Integer id, String cardNo, String address, Citi citi) {
super();
this.id = id;
this.cardNo = cardNo;
this.address = address;
this.citi = citi;
}
public IdCard(String cardNo, String address, Citi citi) {
super();
this.cardNo = cardNo;
this.address = address;
this.citi = citi;
}
public IdCard() {
super();
// TODO Auto-generated constructor stub
}
//此处省略setter/getter方法
}

工具类和配置文件都没有发生改变

dao组件中CitiDao

public interface CitiDao {
//获取每个公民的身份证信息
public List<Citi> getCitiIdCard();
}

CitiDao的配置文件CitiDao.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.ghq.model.dao.CitiDao"> <resultMap type="Citi" id="citiMap">
<id column="citiid" property="id"/>
<result column="citi_name" property="citiName"/> <association property="card" javaType="IdCard">
<id column="cardid" property="id"/>
<result column="card_no" property="cardNo"/>
<result column="address" property="address"/>
</association>
</resultMap> <select id="getCitiIdCard" resultMap="citiMap">
SELECT citi.id citiid, citi.citi_name, card.id cardid, card.card_no, card.address
    FROM citi_tb citi LEFT JOIN card_tb card
    ON citi.id = card.id
</select> </mapper>

单元测试的方法

public class testmybatis {
@Test
public void testgetCitiIdCard(){
SqlSession session = MybatisDb.getSession();
CitiDao citiDao = session.getMapper(CitiDao.class);
List<Citi> citis = citiDao.getCitiIdCard();
session.close();
if (citis != null && citis.size() > 0) {
for (Citi c : citis) {
System.out.println(c.getId()+" "+c.getCitiName()+" "+c.getCard().getId()+" "+c.getCard().getCardNo()+" "+c.getCard().getAddress());
}
}
}
}

多对多

本项目为学生信息表,选课表,选课成绩表之间的关系,即每一个学生可以选多门课,一门课对应多个学生。

项目的目录结构

Oracle中对应的表为

学生表stu_tbl2

课程表cour_tbl2

学生选课表stu_cour_tbl2

表所对应的实体类为

Stu.java

//学生实体类
public class Stu {
//标识属性
private Integer id;
//学生名
private String stuName;
//选修的课程
private List<StuCource> stuCources; //省略有参构造和无参构造函数,setter/getter方法
}

Course.java

//课程实体类
public class Cource {
//标识属性
private Integer id;
//课程名字
private String courceName;
//对应的选课记录
private List<StuCource> stuCources;
//省略有参构造和无参构造函数,setter/getter方法
}

StuCource.java

//选课实体
public class StuCource {
//标识属性
private Integer id;
//对应的学生
private Stu stu;
//对应的课程
private Cource cource;
//对应的成绩
private double score;
//省略有参构造和无参构造函数,setter/getter方法
}

dao组件中

public interface StuDao {
//获取每个学生选修课程信息以及成绩 包含了学生信息 课程信息 成绩信息
public List<Stu> getStuCource();
}

StuDao的配置文件StuDao.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.ghq.model.dao.StuDao"> <resultMap type="Stu" id="stuMap">
<id column="sid" property="id"/>
<result column="stu_name" property="stuName"/>
<collection property="stuCources" ofType="StuCource">
<id column="scid" property="id"/>
<result column="score" property="score"/>
<association property="cource" javaType="Cource">
<id column="cid" property="id"/>
<result column="cour_name" property="courceName"/>
</association>
</collection> </resultMap> <select id="getStuCource" resultMap="stuMap">
SELECT s.id SID,s.stu_name,c.id cid,c.cour_name,sc.id scid,sc.score
FROM stu_cour_tbl2 sc,stu_tbl2 s, cour_tbl2 c
WHERE sc.stu_id(+) = s.id AND sc.cour_id = c.id(+)
</select> </mapper>

单元测试中的方法

public class testmybatis {
@Test
public void testgetStuCource(){
SqlSession session = MybatisDb.getSession();
StuDao studao = session.getMapper(StuDao.class);
List<Stu> stus = studao.getStuCource();
session.close(); if (stus != null && stus.size() > 0) {
for (Stu stu : stus) {
List<StuCource> stuCources = stu.getStuCources();
if (stuCources !=null && stuCources.size() > 0) {
for (StuCource stuCource : stuCources) {
System.out.println(stu.getId()+" "+stu.getStuName()+" "+stuCource.getId()+" "+stuCource.getScore()
+" "+stuCource.getCource().getId()+" "+stuCource.getCource().getCourceName());
} }else {
System.out.println(stu.getId()+" "+stu.getStuName()+" 该学生没有选课");
}
}
}else {
System.out.println("没有学生");
} } }

MyBatis学习(二)---数据表之间关联的更多相关文章

  1. linq查询数值为null的问题以及数据表的关联计算问题

    说明:下面实例都是我进行项目开发时的真实部分代码,毫无保留 一.数据表的关联计算 //把当前年度的分差计算出来,建立两个关联的数据表 try { using(TransactionScope scop ...

  2. SpringBoot+Mybatis 自动创建数据表(适用mysql)

    Mybatis用了快两年了,在我手上的发展史大概是这样的 第一个阶段 利用Mybatis-Generator自动生成实体类.DAO接口和Mapping映射文件.那时候觉得这个特别好用,大概的过程是这样 ...

  3. mybatis学习(五)----实现关联表查询

    一.一对一的表查询 查询班级表中班级号为1的对应的记录(包括教师的具体信息) 1.首先建立数据表 数据表class和techear,class表中只有一个外键techear_id,sql脚本如下: C ...

  4. SQL学习之Insert的特殊用法(插入检索出的数据,表之间的数据复制)

    1.插入检索出的数据 select * from dbo.Customers_1

  5. MyBatis学习(二)

    前言 昨天的博客简单的记录了MyBatis的起源.作用.配置以及一个简单的查询例子.写到一半的时候,觉得已经学会了MyBatis,可是全写完的时候才发现,如果多个参数查询,如何表的名字与类字段名不一样 ...

  6. [转] PostgreSQL学习手册(数据表)

    from: http://www.cnblogs.com/stephen-liu74/archive/2012/04/23/2290803.html 一.表的定义: 对于任何一种关系型数据库而言,表都 ...

  7. PostgreSQL学习手册(数据表)<转>

    一.表的定义: 对于任何一种关系型数据库而言,表都是数据存储的最核心.最基础的对象单元.现在就让我们从这里起步吧.    1. 创建表:    CREATE TABLE products (      ...

  8. MyBatis学习之多表查询

    一对多需求:即一张表class中又含有多张表(teacher,student)内容.现根据class_id 来获取对应的班级信息(包括学生和老师信息) 方式一:嵌套结果 使用嵌套结果映射来处理重复的联 ...

  9. (原创)mybatis学习二,spring和mybatis的融合

    mybatis学习一夯实基础 上文介绍了mybatis的相关知识,这一节主要来介绍mybaits和spring的融合 一,环境搭建 1,jar包下载,下载路径为jar包 2,将包导入到java工程中 ...

随机推荐

  1. How to write date range query in Nest ElasticSearch client?

    Looking at the source code, there are two overloads of the OnField method. When I use the the that t ...

  2. Spring Boot Cookbook 中文笔记

    Spring Boot Cookbook 一.Spring Boot 入门 Spring Boot的自动配置.Command-line Runner RESTful by Spring Boot wi ...

  3. 聊聊Postgres中的IPC之SI Message Queue

    在 PostgreSQL中,每一个进程都有属于自己的共享缓存(shared cache).例如,同一个系统表在不同的进程中都有对应的Cache来缓存它的元组(对于RelCache来说缓存的是一个Rel ...

  4. python3的嵌套函数

    背景 最近在学python3 嵌套函数 顾名思义,即使在函数中还有函数,实现了函数的多级嵌套 def test1(): age = 10 print(age) def test2(): te = 5 ...

  5. C#-MVC基础-模型(Model)、视图(View)和控制器(Controller)

    搜狗百科:http://baike.sogou.com/v25227.htm?fromTitle=MVC MVC全名是Model View Controller,是软件工程中的一种软件架构模式,把软件 ...

  6. prim /kruskal 最小生成树

    #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #inc ...

  7. 【实战】Tomcat管理后台Getshell

    一.制作war包 1.xiaoma.jsp压缩成xiaoma.zip格式,然后修改为xiaoma.war 2.修仙之百度大法 二.部署war包(选择文件,上传即可,不啰嗦啦) 三.C刀连接:http: ...

  8. Mac 10.12安装窗口快速缩放到一定比例的工具Moom

    说明:比如想要窗口只占用屏幕的一半时,我们的做法就是手动调节,而这款软件已经有快速按钮点一下即可. 下载: (链接: https://pan.baidu.com/s/1gfguJth 密码: wqjb ...

  9. try -catch-finally一些要点

    try -catch-finally是处理程序异常时使用,当程序正常时,先走try然后到finally语句,不正常时:程序先走try,然后到catch里面的语句,最后到finally;从上面可以看出, ...

  10. TryParse用法

    int.Parse()是一种类型转换:表示将数字内容的字符串转为int类型. 如果字符串为空,则抛出ArgumentNullException异常: 如果字符串内容不是数字,则抛出FormatExce ...