11.2 注解的使用示例3 一对多关联关系

11.2 注解的使用示例3 一对多关联关系

例如班级和学生是一对多的关联关系,则在查询学生的时候使用@one注解来关联查询班级.
查询班级的时候,使用@Many注解来查询该班级的所有学生.示例项目如下所示:

示例:一对多关联关系

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
G:\workspace_web2\MyAOneToManyTest
├─src
│ ├─db.properties
│ ├─domain
│ │ ├─Clazz.java
│ │ └─Student.java
│ ├─fractory
│ │ └─SqlSessionFactoryTools.java
│ ├─log4j.xml
│ ├─mapper
│ │ ├─ClazzMapper.java
│ │ └─StudentMapper.java
│ ├─mybatis-config.xml
│ ├─tb_clazz_tb_student.sql
│ └─test
│ ├─SelectClazzByIdTest.java
│ └─SelectStudentByIdTest.java
└─WebContent
├─META-INF
│ └─MANIFEST.MF
└─WEB-INF
└─lib
├─ant-1.9.6.jar
├─ant-launcher-1.9.6.jar
├─asm-5.2.jar
├─cglib-3.2.5.jar
├─commons-logging-1.2.jar
├─javassist-3.22.0-CR2.jar
├─log4j-1.2.17.jar
├─log4j-api-2.3.jar
├─log4j-core-2.3.jar
├─mybatis-3.4.5.jar
├─mysql-connector-java-5.1.44-bin.jar
├─ognl-3.1.15.jar
├─slf4j-api-1.7.25.jar
└─slf4j-log4j12-1.7.25.jar

数据库脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 创建tb_clazz表
DROP TABLE IF EXISTS `tb_clazz`;
CREATE TABLE `tb_clazz` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(18) NOT NULL,
`name` varchar(18) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 插入数据到tb_clazz表
INSERT INTO `tb_clazz` VALUES ('1', 'B151516', 'Java基础班');
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(18) DEFAULT NULL,
`sex` varchar(18) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`clazz_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `clazz_id` (`clazz_id`),
CONSTRAINT `tb_student_ibfk_1` FOREIGN KEY (`clazz_id`)
REFERENCES `tb_clazz` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `tb_student` VALUES ('1', '小明', '男', '24', '1');
INSERT INTO `tb_student` VALUES ('2', '小王', '男', '23', '1');
INSERT INTO `tb_student` VALUES ('3', '小芳', '女', '22', '1');
INSERT INTO `tb_student` VALUES ('4', '小丽', '女', '22', '1');

db.properties

1
2
3
4
5
6
# 保存为db.properties文件,然后在mybatis-config.xml中通过下面标签引入:
# <properties resource="db.properties"/>
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
username=root
password=root

log4j.xml

/MyAOneToManyTest/src/log4j.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration
PUBLIC "-//LOG4J//DTD LOG4J//EN"
"https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd" >
<!-- 请在mybatis-config.xml中配置如下设置 -->
<!-- <settings> -->
<!-- <setting -->
<!-- name="logImpl" -->
<!-- value="log4j"/> -->
<!-- </settings> -->
<log4j:configuration>
<appender
name="STDOUT"
class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param
name="ConversionPattern"
value="%5p [%t] %m%n"/>
</layout>
</appender>
<logger name="mapper">
<level value="DEBUG"/>
</logger>
<root>
<level value="ERROR"/>
<appender-ref ref="STDOUT"/>
</root>
</log4j:configuration>

mybatis-config.xml

/MyAOneToManyTest/src/mybatis-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?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">
<!-- 该配置文件包含对 MyBatis 系统的核心设置 -->
<configuration>
<properties resource="db.properties"/>
<settings>
<setting
name="logImpl"
value="log4j"/>
<!-- 要使延迟加载生效必须配置下面两个属性 -->
<setting
name="lazyLoadingEnabled"
value="true"/>
<setting
name="aggressiveLazyLoading"
value="false"/>
</settings>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="pooled">
<property
name="driver"
value="${driver}"/>
<property
name="url"
value="${url}"/>
<property
name="username"
value="${username}"/>
<property
name="password"
value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="mapper.ClazzMapper"/>
<mapper class="mapper.StudentMapper"/>
</mappers>
</configuration>

持久化对象

Clazz.java

/MyAOneToManyTest/src/domain/Clazz.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package domain;

import java.io.Serializable;
import java.util.List;

public class Clazz implements Serializable {
private static final long serialVersionUID = -1924365559257770561L;
private Integer id;
private String code;
private String name;
List<Student> students;

public Clazz() {
}

public Clazz(String code, String name) {
super();
this.code = code;
this.name = name;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Student> getStudents() {
return students;
}

public void setStudents(List<Student> students) {
this.students = students;
}

@Override
public String toString() {
return "Clazz [id=" + id + ", code=" + code + ", name=" + name + "]";
}
}

Student.java

/MyAOneToManyTest/src/domain/Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package domain;

import java.io.Serializable;

public class Student implements Serializable {
private static final long serialVersionUID = 2713166808172094576L;
private Integer id;
private String name;
private String sex;
private Integer age;
private Clazz clazz;

public Student() {
}

public Student(String name, String sex, Integer age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}

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 String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public Clazz getClazz() {
return clazz;
}

public void setClazz(Clazz clazz) {
this.clazz = clazz;
}

@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}

会话工具类

/MyAOneToManyTest/src/fractory/SqlSessionFactoryTools.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package fractory;
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 SqlSessionFactoryTools {
private static SqlSessionFactory sqlSessionFactory = null;
static
{
try
{
InputStream mybatisConfigXML = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(mybatisConfigXML);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static SqlSession getSqlSession()
{
return sqlSessionFactory.openSession();
}
}

mapper接口

ClazzMapper.java

/MyAOneToManyTest/src/mapper/ClazzMapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package mapper;

import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import domain.Clazz;

public interface ClazzMapper {
@Select("select * from tb_clazz where id=#{id}")
@Results({
@Result(column = "id",property = "id", id = true),
@Result(column = "code",property = "code"),
@Result(column = "name",property = "name"),
@Result(column = "id",property = "students",
many = @Many(select = "mapper.StudentMapper.selectStudentsByClassId", fetchType = FetchType.LAZY)
)
})
Clazz selectClazzById(Integer id);

@Select("select * from tb_clazz where id=#{id}")
@Results({
@Result(column = "id",property = "id", id = true),
@Result(column = "code",property = "code"),
@Result(column = "name",property = "name")
})
Clazz selectClazzByUserClazzId(Integer id);
}

StudentMapper.java

/MyAOneToManyTest/src/mapper/StudentMapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package mapper;

import java.util.List;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import domain.Student;

public interface StudentMapper {
@Select("select * from tb_student where id=#{id}")
@Results({
@Result(column = "id",property = "id", id = true),
@Result(column = "name",property = "name"),
@Result(column = "sex",property = "sex"),
@Result(column = "age",property = "age"),
@Result(column = "clazz_id",property = "clazz",
one = @One(select = "mapper.ClazzMapper.selectClazzByUserClazzId", fetchType = FetchType.EAGER)
)
})
Student selectStudentById(Integer id);

@Select("select * from tb_student where clazz_id=#{clazzId}")
@Results({
@Result(column = "id",property = "id", id = true),
@Result(column = "name",property = "name"),
@Result(column = "sex",property = "sex"),
@Result(column = "age",property = "age")
})
List<Student> selectStudentsByClassId(Integer clazzId);
}

fetchType = FetchType.EAGER表示理解加载

测试类

SelectClazzByIdTest.java

/MyAOneToManyTest/src/test/SelectClazzByIdTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package test;

import java.util.List;
import org.apache.ibatis.session.SqlSession;
import domain.Clazz;
import domain.Student;
import fractory.SqlSessionFactoryTools;
import mapper.ClazzMapper;

public class SelectClazzByIdTest {
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFactoryTools.getSqlSession();
// 获取mapper接口代理对象
ClazzMapper clazzMapper = sqlSession.getMapper(ClazzMapper.class);
Clazz clazz = clazzMapper.selectClazzById(1);
System.out.println(clazz.toStringSimple());
// System.out.println(clazz.toString());
System.out.println("--------------------------------------------------------------");
List<Student> students = clazz.getStudents();
students.forEach(student -> System.out.println(student));
// 提交事务
sqlSession.commit();
} catch (Exception e) {
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally {
// 关闭会话
if (sqlSession != null)
sqlSession.close();
}

}
}

运行效果:

1
2
3
4
5
6
7
8
9
10
DEBUG [main] ==>  Preparing: select * from tb_clazz where id=? 
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <== Total: 1
Clazz [id=1, code=B100, name=Java基础班]
--------------------------------------------------------------
DEBUG [main] ==> Preparing: select * from tb_student where clazz_id=?
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] <== Total: 2
Student [id=2, name=小王, sex=男, age=23]
Student [id=4, name=小丽, sex=女, age=22]

SelectStudentByIdTest.java

/MyAOneToManyTest/src/test/SelectStudentByIdTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package test;

import org.apache.ibatis.session.SqlSession;
import domain.Student;
import fractory.SqlSessionFactoryTools;
import mapper.StudentMapper;

public class SelectStudentByIdTest {
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
// 加载mybatis-config.xml,获取SqlSession实例
sqlSession = SqlSessionFactoryTools.getSqlSession();
// 获取mapper接口代理对象
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
// 执行mapper接口方法
Student student = studentMapper.selectStudentById(1);
// System.out.println(student.toString());
System.out.println(student.toStringSimple());
System.out.println("===========================================");
System.out.println(student.getClazz().toString());
// 提交事务
sqlSession.commit();
} catch (Exception e) {
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally {
// 关闭会话
if (sqlSession != null)
sqlSession.close();
}

}
}

运行效果:

1
2
3
4
5
6
7
8
9
DEBUG [main] ==>  Preparing: select * from tb_student where id=? 
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] ====> Preparing: select * from tb_clazz where id=?
DEBUG [main] ====> Parameters: 2(Integer)
DEBUG [main] <==== Total: 1
DEBUG [main] <== Total: 1
Student [id=1, name=小明, sex=男, age=24]
===========================================
Clazz [id=2, code=B101, name=JSP]