MyBatis一对一关联
创建数据库
写两个数据库,一个老师一个教室,使老师成为教室的外键。
create table
classroom(
c_id int
PRIMARY KEY auto_increment
,
c_name
varchar(20),
teacher_id int
);
CREATE table
teacher(
t_id
INT PRIMARY KEY auto_increment
,
t_name
VARCHAR(20)
);
ALTER TABLE classroom
ADD CONSTRAINT fk_teacher_id
FOREIGN KEY (teacher_id
) REFERENCES teacher(t_id
);
INSERT into
teacher(t_name
) values('易老师');
INSERT into
teacher(t_name
) VALUES('而老师');
INSERT into
classroom(c_name
,teacher_id
) values('教室1',1);
INSERT into
classroom(c_name
,teacher_id
) VALUES('教室2',2);
创建实体类
Classroom.java
package com
.mb
.one_one
;
public class Classroom {
private int id
;
private String name
;
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 "Classroom{" +
"id=" + id
+
", name='" + name
+ '\'' +
", teacher=" + teacher
+
'}';
}
}
Teacher.java
package com
.mb
.one_one
;
public class Teacher {
private int id
;
private String 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
+ '\'' +
'}';
}
}
创建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
:命名空间 随便写,随便起名,保证命名空间唯一,建议写地址,包
+文件名
-->
<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
-->
<mapper namespace
="com.mb.one_one.classMapper">
<!-- 在映射文件中配置很多sql语句
-->
<!-- 需求:通过id查询用户表的记录
-->
<!--通过select执行数据库查询
id
:标识映射文件中的sql,
将sql语句封装到mappedStatement对象中,所以将id称为statement的id
parameterType
:制定输入参数的类型,这里制定ing型
#
{}表示一个占位符号
#
{id
}:其中的id表示接受输入的参数,参数名称就是id,如果输入参数就是简单类型,#
{}中的参数名可以任意,可以value或其他名称
resultType:指定sql输入结果的所映射的Java对象,select指定resultType表示将单条记录映射成Java对象。
-->
<!-- 根据id查询我们数据库的信息,我们分三个,
1是直接查询,但是因为实体类的属性名和数据库的字段名对应不上的原因,
因此无法查询出对应的记录,结果应该是
null -->
<!-- 根据学生id信息查询学生信息(和负责老师)
-->
<!-- 两种方法
1. 联表查询
嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集,封装联表查询的数据(去除重复的数据
)-->
<select id
="getClassroom1" parameterType
="int" resultMap
="classroomResultMap" >
select
* from classroom c
,teacher t
WHERE c
.teacher_id
=t_id
AND c
.c_id
=#
{id
}
</select
>
<!-- 使用resultMap映射实体类和字段名的关系
-->
<resultMap id
="classroomResultMap" type
="com.mb.one_one.Classroom">
<id property
="id" column
="c_id" />
<result property
="name" column
="c_name" />
<association property
="teacher" javaType
="com.mb.one_one.Teacher">
<id property
="id" column
="t_id" />
<result property
="name" column
="t_name" />
</association
>
</resultMap
>
<!-- 2. 执行两次查询
嵌套查询:通过执行另外一个
SQL映射语句来返回预期的复杂类型
-->
<select id
="getClassroom2" parameterType
="int" resultMap
="classroomResultMap2" >
select
* FROM classroom where c_id
=#
{id
}
</select
>
<!-- 使用resultMap映射实体类和字段之间的一一对应关系
-->
<resultMap type
="com.mb.one_one.Classroom" id
="classroomResultMap2">
<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.mb.one_one.Teacher">
SELECT t_id id
, t_name name
FROM teacher
WHERE t_id
=#
{id
}
</select
>
</mapper
>
注册classMapper.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">
<!-- properties中还可以配置一些属性名和属性值
-->
<!-- <property name
="jdbc.driver" value
=""/>-->
</properties
>
<!-- 别名定义
-->
<typeAliases
>
<!--针对单个别名定义
type:类型的路径
alias:别名
-->
<!-- <typeAlias type
="com.mb.domain.User" alias
="user" />-->
<!-- 批量定义别名
-->
<!-- 指定报名,mybatis主动把扫描包中的类,自动定义别名,别名就是类型(首字母不分大小写)
-->
<package name
="com.mb.domain" />
</typeAliases
>
<environments
default="development">
<environment id
="development">
<transactionManager type
="JDBC"/>
<!-- 配置数据库连接信息
-->
<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
>
<!-- 加载映射文件
-->
<mapper resource
="com/mb/mapping/userMapper.xml" />
<!-- 注册UserMapper映射接口
-->
<mapper
class="com.mb.mapping.UserMapperI" />
<!-- 注册result_Mapper
.xml 文件
-->
<mapper resource
="com/mb/result_class/result_Mapper.xml" />
<!-- 注册classMapper
.xml文件
-->
<mapper resource
="com/mb/one_one/classMapper.xml" />
</mappers
>
</configuration
>
编写测试类Test_Classroom.java
package com
.mb
.one_one
;
import com
.mb
.util
.MyBatisUtil
;
import org
.apache
.ibatis
.session
.SqlSession
;
public class Test_Classroom {
public void testGetClassroom1(){
SqlSession sqlSession
= MyBatisUtil
.getSqlSession(true);
String statement
= "com.mb.one_one.classMapper.getClassroom1";
Classroom classroom
=sqlSession
.selectOne(statement
,1);
sqlSession
.close();
System
.out
.println(classroom
);
}
public void testGetClassroom2(){
SqlSession sqlSession
= MyBatisUtil
.getSqlSession(true);
String statement
= "com.mb.one_one.classMapper.getClassroom2";
Classroom classroom
=sqlSession
.selectOne(statement
,1);
sqlSession
.close();
System
.out
.println(classroom
);
}
public static void main(String
[] args
){
Test_Classroom test_classroom
=new Test_Classroom();
test_classroom
.testGetClassroom1();
test_classroom
.testGetClassroom2();
}
}
运行结果:
MyBatis一对多关联
创建数据库
CREATE TABLE student(
s_id
INT PRIMARY KEY AUTO_INCREMENT,
s_name
VARCHAR(20),
classroom_id
INT
);
insert
INTO student(s_name
,classroom_id
) values('学生1',1);
insert
INTO student(s_name
,classroom_id
) values('学生2',1);
insert
INTO student(s_name
,classroom_id
) values('学生3',2);
insert
INTO student(s_name
,classroom_id
) values('学生4',2);
insert
INTO student(s_name
,classroom_id
) values('学生5',2);
insert
INTO student(s_name
,classroom_id
) values('学生6',1);
将学生表和教室表连接起来,形成一个教室表,对应两个表的查询。
创建Student.java实体类
package com
.mb
.one_two
;
import com
.mb
.one_one
.Classroom
;
public class Student {
private int id
;
private String 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 "Student{" +
"id=" + id
+
", name='" + name
+ '\'' +
'}';
}
}
修改Classroom类,添加一个List student属性,表示教室拥有学生
package com
.mb
.one_one
;
import com
.mb
.one_two
.Student
;
import java
.util
.List
;
public class Classroom {
private int id
;
private String name
;
private Teacher teacher
;
private List
<Student
> student
;
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
;
}
public List
<Student
> getStudent() {
return student
;
}
public void setStudent(List
<Student
> student
) {
this.student
= student
;
}
@Override
public String
toString() {
return "Classroom{" +
"id=" + id
+
", name='" + name
+ '\'' +
", teacher=" + teacher
+
", student=" + student
+
'}';
}
}
修改classMapper.XML映射文件
把下面的代码添加到映射文件后面就可以
<!-- 一对多关联查询
-->
<!-- 根据教室id查询教室和学生
-->
<!-- 方式一
: 嵌套结果
: 使用嵌套结果映射来处理重复的联合结果的子集
-->
<select id
="getClassroom3" parameterType
="int" resultMap
="classroomResultMap3" >
select
* from classroom c
,student s
,teacher t where c
.teacher_id
=t
.t_id and c
.c_id
=s
.classroom_id and c
.c_id
=#
{id
}
</select
>
<resultMap id
="classroomResultMap3" type
="com.mb.one_one.Classroom" >
<id property
="id" column
="c_id" />
<result property
="name" column
="c_name" />
<association property
="teacher" column
="teacher_id" javaType
="com.mb.one_one.Teacher" >
<id property
="id" column
="t_id" />
<result property
="name" column
="t_name" />
</association
>
<!-- ofType指定students集合中的对象类型
-->
<collection property
="student" ofType
="com.mb.one_two.Student" javaType
="List" >
<id property
="id" column
="s_id" />
<result property
="name" column
="s_name" />
</collection
>
</resultMap
>
MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。
编写测试文件Test_One_Two.java
package com
.mb
.one_two
;
import com
.mb
.one_one
.Classroom
;
import com
.mb
.util
.MyBatisUtil
;
import org
.apache
.ibatis
.session
.SqlSession
;
public class Test_One_Two {
public void testGetClassroom3(){
SqlSession sqlSession
= MyBatisUtil
.getSqlSession(true);
String statement
= "com.mb.one_one.classMapper.getClassroom3";
Classroom classroom
=sqlSession
.selectOne(statement
,2);
sqlSession
.close();
System
.out
.println(classroom
);
}
public static void main(String
[] args
){
Test_One_Two test_one_two
=new Test_One_Two();
test_one_two
.testGetClassroom3();
}
}
测试结果: 为了截图方便,toString方法中我加入了换行,以上的代码中我没有加入。 一对多关联查询还有一种方法,之后我会再加上。