場景:使用三張數據表:student學生表、teacher教師表、position職位表
一個學生可以有多為老師、一位老師可以有多個學生、但是一個老師只能有一個職位:教授、副教授、講師;但是一個職位可以有多個老師:例如教授可以多人
這里則產生了:
一對一關系,從老師角度:老師對職位一對一
一對多關系,從職位角度:職位對老師一對多
多對多關系:查找被教授教導的所有學生(首先職位對老師一對多,老師再對學生再對多、這里便有了一對多對多)
數據表:
老師表
CREATE TABLE `tb_teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t_no` varchar(20) DEFAULT NULL,
`t_name` varchar(20) DEFAULT NULL,
`position_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
/*Data for the table `tb_teacher` */
insert into `tb_teacher`(`id`,`t_no`,`t_name`,`position_id`) values
(1,'163314001','張文遠',1),
(2,'163314002','趙傳智',1),
(3,'163314003','風清揚',2),
(4,'163314004','王匯智',2),
(5,'163314005','汪思遠',3);
學生表
CREATE TABLE `tb_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t_stu_name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
/*Data for the table `tb_student` */
insert into `tb_student`(`id`,`t_stu_name`) values
(1,'趙依'),
(2,'錢邇'),
(3,'張山'),
(4,'李石'),
(5,'王武'),
(6,'馬柳');
職位表
CREATE TABLE `tb_position` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t_pos_name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*Data for the table `tb_position` */
insert into `tb_position`(`id`,`t_pos_name`) values
(1,'教授'),
(2,'副教授'),
(3,'講師');
最后是教師學生關系表
CREATE TABLE `tb_stu_teach` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t_stu_id` int(11) DEFAULT NULL,
`t_teach_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
/*Data for the table `tb_stu_teach` */
insert into `tb_stu_teach`(`id`,`t_stu_id`,`t_teach_id`) values
(1,1,1),
(2,1,2),
(3,1,3),
(4,2,2),
(5,2,3),
(6,2,4),
(7,3,3),
(8,3,4),
(9,3,5),
(10,4,4),
(11,4,5),
(12,4,1);
最后在eclipse中的目錄結構如下:

希望您明白sqlMapConfig該如何配置,以及jdbc.properties和log4j的作用。
貼出POJO中的三個實體(注意:以下的POJO都用了lombok來快速生成setter和getter等,lomok具體使用,請見此文):
Position.java
package com.pojo;
import java.io.Serializable;
import lombok.Data;
@Data
public class Position implements Serializable {
private int id;
private String name;
private Teacher teacher;
}
Student.java
package com.pojo;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@Data
public class Student implements Serializable {
private String id;
private String name;
private List<Teacher> list;
}
Teacher.java
package com.pojo;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@Data
public class Teacher implements Serializable {
private int id;
private String no;
private String name;
private List<Student> studentList;
private Position pos;
}
注意:關系表不用以實體表示出來,表示外鍵關系的ID也不用寫在實體中(一般我們也不使用外鍵)
再貼另一個MybatisUtil.java工具類
package com.util;
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 {
private static SqlSessionFactory sqlSessionFactory = null;
static {
String resource = "sqlMapConfig.xml";
// 首先要加載核心配置文件:從classpath下開始找。
InputStream in;
try {
in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
}
一對一:老師對職位
TeacherMapper.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.mapper.TeacherMapper">
<resultMap type="Teacher" id="teacherPositionResultMap">
<id property="id" column="id"/>
<result property="no" column="t_no"/>
<result property="name" column="t_name"/>
<!-- association:配置的一對一屬性 -->
<!-- property:名字
javaType:類型
-->
<association property="pos" javaType="Position">
<id property="id" column="id"/>
<result property="name" column="t_pos_name"/>
</association>
</resultMap>
<!-- 一對一關聯查詢,查詢老師及其對應的職位 -->
<!-- 注意:id不能相同,當多個值傳入,比如包裝類的時候,我們才能夠用SQL片段的形式來做if判斷,單個值是不行的 -->
<select id="queryTeacherPositionResultMapById" resultMap="teacherPositionResultMap" parameterType="Integer">
SELECT *
FROM tb_teacher t
LEFT JOIN tb_position p
ON t.position_id = p.id
where t.id = #{id}
</select>
<select id="queryTeacherPositionResultMap" resultMap="teacherPositionResultMap">
SELECT *
FROM tb_teacher t
LEFT JOIN tb_position p
ON t.`position_id` = p.id
</select>
</mapper>
TeacherMapper.java接口
package com.mapper;
import java.util.List;
import com.pojo.Teacher;
public interface TeacherMapper {
public List<Teacher> queryTeacherPositionResultMap();
public Teacher queryTeacherPositionResultMapById(Integer id);
}
測試一對一:
package com.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.mapper.TeacherMapper;
import com.pojo.Teacher;
import com.util.MyBatisUtil;
public class TestOneToOne {
@Test
public void testOneToOne() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
System.err.println(sqlSession);
TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
List<Teacher> list = teacherMapper.queryTeacherPositionResultMap();
System.out.println(list);
Teacher teacher = teacherMapper.queryTeacherPositionResultMapById(1);
System.out.println(teacher);
}
}
一對多:職位對老師
PositionMapper.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.mapper.PositionMapper">
<resultMap type="Position" id="positionTeacherResultMap">
<id property="id" column="id"/>
<result property="name" column="t_pos_name"/> <!-- t_name -->
<!--
property同association中的一樣是屬性名稱(javaBean中的);
javaType也同association中的是類型,
最后多了一個OfType,因為一對多,不像一對一是單個的!我們這里是List集合,list和List都可以。
一對多其中是放的一個集合所以這個是集合的泛型的類型,這里我們的list中放的是Teacher:
所以這里是Teacher。
-->
<collection property="teacherList" javaType="List" ofType="Teacher" >
<!--
一對多出現的問題:
當數據庫表中,主表的主鍵id和明細表的 ...
當表中的字段名相同時怎么辦?多表聯查?
注意:Mybatis中做多表聯查的時候,不管是
一對一、一對多、一對多對多:多對多:
都不能有字段重名的情況:不管是主鍵還是普通字段。
一旦字段重名的話,就會造成數據少自動賦值,或者覆蓋,甚至重復賦值!
規避和解決此類問題的方法:
1.盡量不要表間重名,mybatis里處理起來很麻煩!id和普通字段都是。
但是在表多的時候,很難不會出現字段重名的情況。主鍵id最容易重名!
那么就要用以下的辦法了!
2.在mybatis中寫原生SQL進行查詢的時候,查的字段盡可能的少,這
也影響速率,強烈禁止使用*,用多少查多少!這樣也能及時發現字段重
名的情況!
3.最后如果真的需要查出重名的字段,並且修改數據庫字段名造成的更改
過大,這里推薦的方式是給字段取別名,在寫resultMap映射的時候,其
中的column屬性就填寫SQL語句中查出字段取的別名,這樣就能解決重復
問題了!
-->
<id property="id" column="t_id"/>
<result property="no" column="t_no"/>
<result property="name" column="t_name"/>
</collection>
</resultMap>
<select id="queryPositionTeacherResultMapById" resultMap="positionTeacherResultMap"
parameterType="Integer">
<!--
SELECT *
FROM tb_position p
LEFT JOIN tb_teacher t
ON p.id = t.position_id
WHERE p.id = #{id}
-->
SELECT
p.*,
t.id t_id,
t.t_name,
t.t_no
FROM tb_position p
LEFT JOIN tb_teacher t
ON p.id = t.position_id
WHERE p.id = #{id}
</select>
<select id="queryPositionTeacherResultMap" resultMap="positionTeacherResultMap" >
<!--
SELECT *
FROM tb_position p
LEFT JOIN tb_teacher t
ON p.id = t.position_id
-->
SELECT
p.*,
t.id t_id,
t.t_name,
t.t_no
FROM tb_position p
LEFT JOIN tb_teacher t
ON p.id = t.position_id
</select>
</mapper>
TeacherMapper.java接口
package com.mapper;
import java.util.List;
import com.pojo.Position;
public interface PositionMapper {
public Position queryPositionTeacherResultMapById(Integer id);
public List<Position> queryPositionTeacherResultMap();
}
測試一對多:
package com.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.mapper.PositionMapper;
import com.pojo.Position;
import com.util.MyBatisUtil;
public class TestOneToMany {
@Test
public void testOneToMany() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
List<Position> list = positionMapper.queryPositionTeacherResultMap();
System.out.println(list);
Position pos = positionMapper.queryPositionTeacherResultMapById(1);
System.out.println(pos);
}
}
多對多:職位是教授的老師教授的所有學生(一對多對多:只要你願意可以一直對多下去...)
PositionMapper.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.mapper.PositionMapper">
<resultMap type="Position" id="positionStudentResultMap">
<!-- <id property="id" column="id"/> -->
<result property="name" column="t_pos_name"/>
<collection property="teacherList" javaType="List" ofType="Teacher" >
<result property="name" column="t_name"/>
<collection property="studentList" javaType="List" ofType="Student">
<result property="name" column="t_stu_name"/>
</collection>
</collection>
</resultMap>
<select id="selectPositionStudentByPosId" resultMap="positionStudentResultMap" parameterType="Integer">
SELECT p.t_pos_name, t.t_name, s.t_stu_name
FROM tb_position p
INNER JOIN tb_teacher t ON p.id = t.position_id
LEFT JOIN tb_stu_teach st ON st.t_teach_id = t.id
LEFT JOIN tb_student s ON s.id = st.t_stu_id
WHERE p.id = #{id}
</select>
</mapper>
PositionMapper.java接口
package com.mapper;
import com.pojo.Position;
public interface PositionMapper {
public Position selectPositionStudentByPosId(Integer id);
}
測試:
package com.test;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.mapper.PositionMapper;
import com.pojo.Position;
import com.util.MyBatisUtil;
public class TestManyToMany {
@Test
public void testManyToMany() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
Position pos = positionMapper.selectPositionStudentByPosId(1);
System.out.println(pos);
}
}
