想要了解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. [Linux] 如何在 Linux 中提取随机数

    如何在 Linux 中提取随机数 一.设备文件 /dev/random & /dev/urandom 字符特殊文件 /dev/random 和 /dev/urandom (存在于Linux 1 ...

  2. SpringMvc @RequestMapping原理

    讲这个之前,我们得先知道在SpringMvc启动时,会加载所有的Bean类,就是加了@Controller,@Component等组件标识的类,然后会把@RequestMapping的方法也加入到一个 ...

  3. spark持久化

    spark持久化:cache .persist.checkpoint 一.cache持久化 cache实际上是persist的一种简化方式,是一种懒执行的,执行action类算子才会触发,cahce后 ...

  4. [性能测试]:关于MQ协议脚本开发

    消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们. 银行脚本使用MQ通信的较多,下面介绍一个MQ的脚本: M ...

  5. Q143 重排链表

    给定一个单链表 L:L0→L1→-→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例 1: ...

  6. Ubuntu里面vi编辑器在编辑文本时 如何在所有行行首或行尾插入字符

    例如:我这里是在每一行行首插入new :%s/^/new 在20,50行首插入new :20,50s/^/new 在每一行行尾插入@@ :%s/$/@@ 在20到50行行尾插入## :20,50s/$ ...

  7. wap 往下拉自动加载更多数据

    var stop=true; $(window).scroll(function(){ totalheight = parseFloat($(window).height()) + parseFloa ...

  8. JDBC处理Transaction

    package com.ayang.jdbc; import java.sql.*; /** * transaction的构成,随便写一句insenrt,一执行executeUpdate(),它自动提 ...

  9. 《LeetBook》leetcode题解(8): String to Integer (atoi) [E]——正负号处理

    我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...

  10. 关于chrome下的bug

    最近看了大神的一篇文章,于是尝试了一下里面说的bug以及修复 1.Chrome下absolute绝对定位元素部分display属性值不渲染bug 首先还原一下bug.. ff下的下效果 点击按钮后的效 ...