对于mybatis中 一对多,多对一情景的理解,以及代码实现
在学习b站狂神的Mybatis教程中,一对多还有多对一情景中,狂神用现实生活中的老师还有学生的例子做了一个场景,即一个老师对应多个学生,还有多个学生对应一个老师。但是他的数据库表中使用了外键,那么我就想能不能不用外键也可以达成这样的目的呢?
首先我们创建一个名字叫school1的数据库
还有学生表以及老师表,然后给他们插入几条数据
create database school2 `school2` create table student( `id` int(20) not null, `name` varchar(20) not null, `tid` int(20) not null, primary key(`id`) )engine=innodb default charset=utf8 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1'); create table teacher( `id` int(20) not null, `name` varchar(20) not null, primary key(`id`) )engine=innodb default charset=utf8 insert into `teacher` (`id`,`name`)values('1','丽丽');
之后我们进行Mybatis的项目结构搭建:

首先是多对一:注意在构建pojo实体类的student类时,要把老师的属性也加入进去
student实体类:
public class Student { private int id; private String name; private int tid; private Teacher teacher; public Student() { } public Student(int id, String name, int tid) { this.id = id; this.name = name; this.tid = tid; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.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 int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", tid=" + tid + ", teacher=" + teacher + '}'; } }
teacher实体类:
public class Teacher { private int id; private String name; public Teacher() { } public Teacher(int id, String name) { this.id = id; this.name = 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 + '\'' + '}'; } }
之后编写student的接口
public interface StudentMapper { List<Student> getStudent(); }
然后对这个接口进行对应的xml文件的配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.jin.dao.StudentMapper"> <select id="getStudent" resultMap="studentTeacher"> select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid from school1.student,school1.teacher where student.tid=teacher.id </select> <resultMap id="studentTeacher" type="student"> <result property="id" column="sid"/> <result property="tid" column="stid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> </association> </resultMap> </mapper>
以及关键的mybatis的核心配置文件:
<?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"/> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--可以给实体类起别名 --> <typeAliases> <typeAlias type="com.jin.pojo.Student" alias="student"/> <typeAlias type="com.jin.pojo.Teacher" alias="teacher"/> </typeAliases> <environments default="development"> <environment id="development"> <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="com.jin.dao.TeacherMapper"/> <mapper class="com.jin.dao.StudentMapper"/> </mappers> </configuration>
通过以上的代码可以看出,对于StudentMapper接口的xml核心配置文件的书写最为关键
我们把查找的对应sql语句写完后要用resaultmap这个属性进行配置,之后我们在进行相应的resaultmap标签的编写
<select id="getStudent" resultMap="studentTeacher"> select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid from school1.student,school1.teacher where student.tid=teacher.id </select> <resultMap id="studentTeacher" type="student"> <result property="id" column="sid"/> <result property="tid" column="stid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> </association> </resultMap>
其中 property属性是映射到你在项目中编写的实体类当中的属性,而后column实行是你在sql语句中写的属性
这里要注意:因为你的 resultmap标签的属性是student那么下面配置的属性中就不能出现有关于teacher的属性
那么我们要怎样来配置teacher的属性呢?
我们就用到了association标签来配置,因为teacher变量的类型是引用类型那么在Javatap中就要填写对应的Teacher类
之后再association标签里面配置你sql中其他出现的属性
然后编写测试类:
测试类要用到的工具类:
public class MybatisUtils { static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(true); } }
测试类:
@Test public void Test2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> student = mapper.getStudent(); for (Student student1 : student) { System.out.println(student1); } sqlSession.close(); }
可以看到运行结果为:

这样多对一的场景就实现了
一对多
一对多的实现跟多对一差不多,就是实体类还有接口的xml配置文件有变化
teacher实体类:(在老师的属性中加入了学生集合来实现一对多)
public class Teacher { private int id; private String name; private List<Student> students; public Teacher() { } public Teacher(int id, String name, List<Student> students) { this.id = id; this.name = name; this.students = students; } 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 List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } @Override public String toString() { return "Teacher{" + "id=" + id + ", name='" + name + '\'' + ", students=" + students + '}'; } }
teachermapper接口:
public interface TeacherMapper { Teacher getTeacher(@Param("id") int id); }
xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.jin.dao.TeacherMapper"> <resultMap id="teacherStudent" type="teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="tid" column="stid"/> <result property="name" column="sname"/> </collection> </resultMap> <select id="getTeacher" resultMap="teacherStudent"> select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid from school1.student,school1.teacher where student.tid=teacher.id and tid=#{id} </select> </mapper>
注意我们要配置sql中需要的student属性时就要用collection标签了,然后要用oftype属性来取出集合student中的属性
之后测试类:
public class MyTest { @Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); } }
最后运行结构:

运行结果:Teacher{id=1, name='丽丽', students=[Student{id=1, name='小明', tid=1}, Student{id=2, name='小红', tid=1}, Student{id=3, name='小芳', tid=1}, Student{id=4, name='小李', tid=1}, Student{id=5, name='小张', tid=1}]}
这样不用外键的一对多,还有多对一就实现了
浙公网安备 33010602011771号