Mybatis【多表連線】
我們在學習Hibernate的時候,如果表涉及到兩張的話,那麼我們是在對映檔案中使用<set>
..<many-to-one>
等標籤將其的對映屬性關聯起來的...那麼在我們Mybatis中又怎麼做呢???
先來回顧一下我們SQL99的語法:
一)內連線(等值連線):查詢客戶姓名,訂單編號,訂單價格
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c inner join orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c join orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c,orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c join orders o
on c.id = o.customers_id;
---------------------------------------------------
注意:內連線(等值連線)只能查詢出多張表中,連線欄位相同的記錄
二)外連線:按客戶分組,查詢每個客戶的姓名和訂單數
---------------------------------------------------
左外連線:
select c.name,count(o.isbn)
from customers c left outer join orders o
on c.id = o.customers_id
group by c.name;
---------------------------------------------------
右外連線:
select c.name,count(o.isbn)
from orders o right outer join customers c
on c.id = o.customers_id
group by c.name;
---------------------------------------------------
注意:外連線既能查詢出多張表中,連線欄位相同的記錄;又能根據一方,將另一方不符合相同記錄強行查詢出來
三)自連線:求出AA的老闆是EE
---------------------------------------------------
內自連線:
select users.ename,boss.ename
from emps users inner join emps boss
on users.mgr = boss.empno;
---------------------------------------------------
外自連線:
select users.ename,boss.ename
from emps users left outer join emps boss
on users.mgr = boss.empno;
---------------------------------------------------
注意:自連線是將一張表,通過別名的方式,看作多張表後,再進行連線。
這時的連線即可以採用內連線,又可以採用外連線
複製程式碼
由於我們Mybatis中並沒有像Hibernate這樣全自動化的,因此我們是沒有<set>
..<many-to-one>
等標籤的,我們還是使用手寫SQL語句來使我們的關聯屬性連線起來...
一對一
需求:
- 學生和身份證
設計表:
--mysql
create table cards(
cid int(5) primary key,
cnum varchar(10)
);
create table students(
sid int(5) primary key,
sname varchar(10),
scid int(5),
constraint scid_fk foreign key(scid) references cards(cid)
);
insert into cards(cid,cnum) values(1,'111');
insert into students(sid,sname,scid) values(1,'哈哈',1);
select * from cards;
select * from students;
複製程式碼
實體
/**
* 身份證(單方)
* @author AdminTC
*/
public class Card {
private Integer id;
private String num;
public Card(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
}
複製程式碼
/**
* 學生(單方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private Card card;//關聯屬性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}
複製程式碼
對映檔案
由於我們有兩個實體,因此我們會有兩個對映檔案
Student對映檔案
<?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="studentNamespace">
<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>
</mapper>
複製程式碼
Card對映檔案
<?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="cardNamespace">
<resultMap type="zhongfucheng2.Card" id="cardMap">
<id property="id" column="cid"/>
<result property="num" column="cnum"/>
</resultMap>
</mapper>
複製程式碼
DAO層
現在我想根據學生的編號查詢學生的資訊和身份證資訊!
由於該查詢著重是查詢學生的資訊,於是我們在學生的對映檔案中寫SQL語句
按照需求,我們寫出來的SQL語句是這樣子的。
select * from zhongfucheng.students s,zhongfucheng.cards c where c.cid = s.scid and sid=1;
複製程式碼
我來看一下查詢結果:
我們的實體與對映表中,Student實體是沒有關聯其他的欄位的,僅僅是寫出了該實體的自帶的屬性。
<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>
複製程式碼
明顯地,我們Student是不能封裝返回的結果,因此我們需要將關聯屬性進行關聯起來!
<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<!--
property寫的是在Student實體中寫關聯欄位的屬性變數名稱
resultMap寫的是對映檔案中的名稱空間.id
-->
<association property="card" resultMap="cardNamespace.cardMap"/>
</resultMap>
複製程式碼
我們關聯了以後,Student實體就能夠封裝返回的結果了
<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<!--
property寫的是在Student實體中寫關聯欄位的屬性變數名稱
resultMap寫的是對映檔案中的名稱空間.id
-->
<association property="card" resultMap="cardNamespace.cardMap"/>
</resultMap>
<select id="findById" parameterType="int" resultMap="studentMap">
select * from zhongfucheng.students s,zhongfucheng.cards c where c.cid = s.scid and sid=#{id};
</select>
複製程式碼
查詢編號為1的學生資訊【包括身份證編號】
public Student findById(int id) throws Exception {
//得到連線物件
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
return sqlSession.selectOne("studentNamespace.findById", id);
/* sqlSession.commit();*/
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
Student student = studentDao.findById(1);
System.out.println(student.getId() + "----" + student.getName() + "----" + student.getCard().getNum());
}
複製程式碼
一對多
需求:
- 一個班級有多個學生,查詢java學科有哪些學生資訊
設計資料庫表
create table grades(
gid int(5) primary key,
gname varchar(10)
);
create table students(
sid int(5) primary key,
sname varchar(10),
sgid int(5),
constraint sgid_fk foreign key(sgid) references grades(gid)
);
insert into grades(gid,gname) values(1,'java');
insert into students(sid,sname,sgid) values(1,'哈哈',1);
insert into students(sid,sname,sgid) values(2,'呵呵',1);
select * from grades;
select * from students;
複製程式碼
實體
package zhongfucheng2;
import java.util.ArrayList;
import java.util.List;
/**
* 學科(單方)
* @author AdminTC
*/
public class Grade {
private Integer id;
private String name;
private List<Student> studentList = new ArrayList<Student>();//關聯屬性
public Grade(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
複製程式碼
package zhongfucheng2;
/**
* 學生(多方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private Grade grade;//關聯屬性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
複製程式碼
對映檔案SQL語句
<mapper namespace="studentNamespace">
<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>
<!--查詢選修的java學科有多少位學生-->
<!--由於我們只要查詢學生的名字,而我們的實體studentMap可以封裝學生的名字,那麼我們返回studentMap即可,並不需要再關聯到學科表-->
<select id="findByGrade" parameterType="string" resultMap="studentMap">
select s.sname,s.sid from zhongfucheng.students s,zhongfucheng.grades g WHERE s.sgid=g.gid and g.gname=#{name};
</select>
</mapper>
<?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="gradeNamespace">
<resultMap type="zhongfucheng2.Grade" id="gradeMap">
<id property="id" column="gid"/>
<result property="name" column="gname"/>
</resultMap>
</mapper>
複製程式碼
DAO
public List<Student> findByGrade(String grade) throws Exception {
//得到連線物件
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
return sqlSession.selectList("studentNamespace.findByGrade", grade);
/* sqlSession.commit();*/
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
List<Student> student = studentDao.findByGrade("java");
for (Student student1 : student) {
System.out.println(student1.getName());
}
}
複製程式碼
多對多
需求:
- 學生和課程
資料庫表
create table students(
sid int(5) primary key,
sname varchar(10)
);
create table courses(
cid int(5) primary key,
cname varchar(10)
);
create table middles(
msid int(5),
mcid int(5),
primary key(msid,mcid)
);
insert into students(sid,sname) values(1,'哈哈');
insert into students(sid,sname) values(2,'呵呵');
insert into courses(cid,cname) values(1,'java');
insert into courses(cid,cname) values(2,'android');
insert into middles(msid,mcid) values(1,1);
insert into middles(msid,mcid) values(1,2);
insert into middles(msid,mcid) values(2,1);
insert into middles(msid,mcid) values(2,2);
select * from students;
select * from courses;
select * from middles;
複製程式碼
實體
package cn.itcast.javaee.mybatis.many2many;
import java.util.ArrayList;
import java.util.List;
/**
* 課程(多方)
* @author AdminTC
*/
public class Course {
private Integer id;
private String name;
private List<Student> studentList = new ArrayList<Student>();//關聯屬性
public Course(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
複製程式碼
package cn.itcast.javaee.mybatis.many2many;
import java.util.ArrayList;
import java.util.List;
/**
* 學生(多方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private List<Course> courseList = new ArrayList<Course>();//關聯屬性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
}
複製程式碼
對映檔案
<?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="courseNamespace">
<resultMap type="cn.itcast.javaee.mybatis.many2many.Course" id="courseMap">
<id property="id" column="cid"/>
<result property="name" column="cname"/>
</resultMap>
<!-- 查詢哈哈選學了哪些課程 -->
<select id="findAllByName" parameterType="string" resultMap="courseMap">
select c.cid,c.cname
from students s inner join middles m
on s.sid = m.msid
inner join courses c
on m.mcid = c.cid
and s.sname = #{name}
</select>
</mapper>
複製程式碼
<?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="studentNamespace">
<resultMap type="cn.itcast.javaee.mybatis.many2many.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>
<select id="findAllByCourseName" parameterType="string" resultMap="studentMap">
select s.sname
from students s inner join middles m
on s.sid = m.msid
inner join courses c
on m.mcid = c.cid
and c.cname = #{name}
</select>
</mapper>
複製程式碼
DAO
package cn.itcast.javaee.mybatis.many2many;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import cn.itcast.javaee.mybatis.util.MybatisUtil;
/**
* 持久層
* @author AdminTC
*/
public class StudentCourseDao {
/**
* 查詢哈哈選學了哪些課程
* @param name 表示學生的姓名
*/
public List<Course> findAllByName(String name) throws Exception{
SqlSession sqlSession = null;
try{
sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList("courseNamespace.findAllByName",name);
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
/**
* 查詢java課程有哪些學生選修
* @param name 表示學生的課程
*/
public List<Student> findAllByCourseName(String name) throws Exception{
SqlSession sqlSession = null;
try{
sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList("studentNamespace.findAllByCourseName",name);
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
public static void main(String[] args) throws Exception{
StudentCourseDao dao = new StudentCourseDao();
List<Course> courseList = dao.findAllByName("哈哈");
System.out.print("哈哈選學了" + courseList.size()+"個課程,分別是:");
for(Course c : courseList){
System.out.print(c.getName()+" ");
}
System.out.println("\n-----------------------------------------------------");
List<Student> studentList = dao.findAllByCourseName("android");
System.out.println("選修了android課程的學生有"+studentList.size()+"個,分別是:");
for(Student s : studentList){
System.out.print(s.getName()+" ");
}
}
}
複製程式碼
總結
對於Mybatis的多表連線就非常簡單了,由於SQL語句全是由我們自己寫,如果我們返回的資料型別在當前的實體中是不夠封裝的話,那麼我們只要再關聯對應的對映屬性就行了!
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y