紧接着上一篇 MyBatis 一对多关联映射,这里介绍 MyBatis 一对多关联关系的实现:一个班级有多个学生(一对多),一个学生只属于一个班级(多对一)。
注:MyBatis 下载地址https://github.com/mybatis/mybatis-3/releases
程序使用的是 MySQL 数据库。
登录 MySQL 后新建一个数据库并取名 mybatis 。
这里需要两个表 :班级表和学生表 创建班级表 tb_class 并插入一条数据:
mysql> create table tb_class( -> c_id int primary key auto_increment, -> c_name varchar(20)); insert into tb_class(c_name) values('Class One');创建学生表 tb_student 并插入三条数据:
mysql> create table tb_student( -> s_id int primary key auto_increment, -> s_name varchar(20), -> s_sex varchar(10), -> s_age int, -> s_c_id int, -> foreign key(s_c_id) references tb_class(c_id)); insert into tb_student(s_name,s_sex,s_age,s_c_id) values('Tom','male',18,1); insert into tb_student(s_name,s_sex,s_age,s_c_id) values('Jack','male',19,1); insert into tb_student(s_name,s_sex,s_age,s_c_id) values('Rose','female',18,1);(1)首先在 Eclipse 里新建一个动态 Web 工程(Dynamic Web Project),命名为 OneToMany 。 (2)将前面提到的三个 jar 包拷贝到工程的/WebContent/WEB-INF/lib/ 目录下,如下:
在Java Resources/src 的包 gler.mybatis.onetomany.model 下新建类 Student.java,一个学生具有 id、name、sex、age 属性。
Student.java 的代码如下:
package gler.mybatis.onetomany.model; public class Student { private Integer id; private String name; private String sex; private Integer age; public Student() { } public Student(Integer id, String name, String sex, Integer age) { this.id = id; 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; } }再在包 gler.mybatis.onetomany.model 下新建类 Classes.java,一个班级有 id,name,students 属性。List<Student> students 用来表示一对多的关系,一个班级可以有多个学生。students 是一个 List 集合。
Classes.java 的代码如下:
package gler.mybatis.onetomany.model; import java.util.List; public class Classes { private Integer id; private String name; // 班级和学生是一对多的关系,即一个班级可以有多个学生 private List<Student> students; public Classes() { } public Classes(Integer id, String name, List<Student> students) { this.id = id; this.name = name; this.students = students; } 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> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }新建包 gler.mybatis.onetomany.mapper ,并在包下新建方法接口 ClassesMapper.java。
ClassesMapper 接口的代码如下:
package gler.mybatis.onetomany.mapper; import gler.mybatis.onetomany.model.Classes; public interface ClassesMapper { /* * 根据 id 查询班级 Classes 和它的学生 * @param id * @return * @throws Exception */ public Classes selectClassAndStudentsById(Integer id) throws Exception; }在包 gler.mybatis.onetomany.mapper 下新建映射文件 ClassesMapper.xml ,映射文件与接口名相同。
ClassesMapper.xml 的配置如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="gler.mybatis.onetomany.mapper.ClassesMapper"> <select id="selectClassAndStudentsById" parameterType="int" resultMap="classmap"> select c.c_id,c.c_name,s.s_id,s.s_name,s.s_sex,s.s_age from tb_class c left outer join tb_student s on c.c_id = s.s_c_id where c.c_id=#{id} </select> <!-- resultMap:映射实体类和字段之间的一一对应的关系 --> <resultMap id="classmap" type="Classes"> <id property="id" column="c_id" /> <result property="name" column="c_name" /> <!-- 一对多关联映射:collection --> <collection property="students" ofType="Student"> <id property="id" column="s_id" /> <result property="name" column="s_name" /> <result property="sex" column="s_sex" /> <result property="age" column="s_age" /> </collection> </resultMap> </mapper>在这里,采用的是集合的嵌套结果映射的方式,使用了 <collection.../> 元素映射一对多的关联关系。
如果想要 Student 的结果映射可以重用,我们可以定义一个 Student 类型的 resultMap,再在 <collection.../> 中用 resultMap= 引用。
在项目目录 /Java Resources/src 下新建 MyBatis 配置文件 mybatis.cfg.xml ,用来配置 Mybatis 的运行环境、数据源、事务等。
mybatis.cfg.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> <!-- 为JavaBean起类别名 --> <typeAliases> <!-- 指定一个包名起别名,将包内的 Java 类的类名作为类的类别名 --> <package name="gler.mybatis.onetomany.model" /> </typeAliases> <!-- 配置mybatis运行环境 --> <environments default="development"> <environment id="development"> <!-- type="JDBC" 代表直接使用 JDBC 的提交和回滚设置 --> <transactionManager type="JDBC" /> <!-- POOLED 表示支持JDBC数据源连接池 --> <!-- 数据库连接池,由 Mybatis 管理,数据库名是 mybatis,MySQL 用户名 root,密码为 root --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <mappers> <!-- 通过 mapper 接口包加载整个包的映射文件 --> <package name="gler/mybatis/onetomany/mapper" /> </mappers> </configuration>使用日志文件是为了查看控制台输出的 SQL 语句。
在项目目录 /Java Resources/src 下新建 MyBatis 日志记录文件 log4j.properties ,在里面添加如下内容:
# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n在包 gler.mybatis.onetomany.test 下新建测试类 Test.java ,代码如下:
package gler.mybatis.onetomany.test; 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; import java.util.List; import gler.mybatis.onetomany.mapper.ClassesMapper; import gler.mybatis.onetomany.model.Classes; import gler.mybatis.onetomany.model.Student; public class Test { private static SqlSessionFactory sqlSessionFactory; public static void main(String[] args) { // Mybatis 配置文件 String resource = "mybatis.cfg.xml"; // 得到配置文件流 InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } // 创建会话工厂,传入 MyBatis 的配置文件信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 通过工厂得到 SqlSession SqlSession session = sqlSessionFactory.openSession(); ClassesMapper mapper = session.getMapper(ClassesMapper.class); try { Classes classes = mapper.selectClassAndStudentsById(1); session.commit(); System.out.println("班级信息:"+classes.getId()+","+classes.getName()); List<Student> students = classes.getStudents(); System.out.println("班级的所有学生信息:"); for(Student stu:students){ System.out.println(stu.getId()+","+stu.getName()+","+stu.getSex()+","+stu.getAge()); } } catch (Exception e) { e.printStackTrace(); session.rollback(); } // 释放资源 session.close(); } }运行测试类 Test.java,查询 id 为1的班级的所有信息及其班主任的信息。
输出信息与数据库中的数据一致。
注:以上实现的是一对多,多对一的实现和一对一的方式一样,这里不再赘述。
参考链接
mybatis中文文档《Spring+MyBatis 企业应用实战》