Mybatis关系映射
mybatis关系映射分类:
- 一对一
- 一对多
- 多对一
- 多对多
映射关系可以通过resulttype和resultmap进行设置。本文只讲述resultMap方式。
一对一
一般通过外键关联,即A保存B的主键作为A中的一类。
例如:Person(人)-Card(身份证) 人和身份证信息是一对一对应的。
-
创建javaBean对象。Person类和Card类。其中Person类中包含Card类型的属性。
public class Person implements Serializable { private Long id; private String UserName; private Card card; //get set方法省略 } public class Card implements Serializable { private Long id; private String name; //get set方法省略 }
-
数据库建表。创建tb_person和tb_card表。
CREATE TABLE `tb_person` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `cardid` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE `tb_card` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
-
创建personMapper.xml
<resultMap id="PersonMap" type="com.Mapping.entity.Person"> <id property="id" column="id"></id> <result property="UserName" column="username"></result> <association property="card" javaType="com.Mapping.entity.Card"> <id property="id" column="id"></id> <result property="name" column="name"></result> </association> </resultMap> <select id="getPersonById" parameterType="Long" resultMap="PersonMap"> SELECT p.id,p.username,p.cardid,c.name FROM tb_person p,tb_card c WHERE p.cardid = c.id AND p.id=#{id} </select>
-
测试结果
DEBUG [main] - ==> Preparing: SELECT p.id,p.username,p.cardid,c.name FROM tb_person p,tb_card c WHERE p.cardid = c.id AND p.id=? DEBUG [main] - ==> Parameters: 1(Long) DEBUG [main] - <== Total: 1 Person{id=1, UserName='zhangsan', card=Card{id=1, name='身份证1'}}
在标签中添加子标签标签。
association标签属性
属性 描述 property 指定映射到的实体类对象属性,与表字段一一对应; column 指定数据表中的列 javaType 指定映射到实体对象属性的类型; select 指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询;由于嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,
因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大的消耗数据库性能并且会降低查询效率。因此很少使用这种方法。typeHandler 类型处理器 resultMap 结果返回类型 jdbcType 数据库中列的类型 fetchType 指定在关联查询时是否启用延迟加载。该属性有lazy和eager两个属性值,默认值为lazy(即默认关联映射延迟加载) columnPrefix 当连接多个表时,你可能会不得不使用列别名来避免在 ResultSet
中产生重复的列名。指定 columnPrefix 列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中。 详细说明请参考后面的例子。notNullColumn 默认情况下,在至少一个被映射到属性的列不为空时,子对象才会被创建。 你可以在这个属性上指定非空的列来改变默认行为,指定后,Mybatis 将只在这些列非空时才创建一个子对象。可以使用逗号分隔来指定多个列。默认值:未设置(unset) autoMapping 如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。注意,本属性对外部的结果映射无效,所以不能搭配 select
或resultMap
元素使用。默认值:未设置(unset)。foreignColumn 指定外键对应的列名,指定的列将与父类型中 column
的给出的列进行匹配。resultSet 指定用于加载复杂类型的结果集名字。
一对多和多对一
Customer(客户)-Orders(订单)
-
创建javaBean对象。创建Customer和Orders类
public class Customer { private Long customerid; private String customername; private List<Orders> orders; } public class Orders { private Long orderid; private String ordername; private Customer customer; }
-
数据库建表。tb_customer和tb_order
CREATE TABLE `tb_customer` ( `customerid` int(11) NOT NULL AUTO_INCREMENT, `customername` varchar(255) DEFAULT NULL, PRIMARY KEY (`customerid`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE `tb_order` ( `orderid` int(11) NOT NULL AUTO_INCREMENT, `ordername` varchar(255) DEFAULT NULL, `customerid` int(11) DEFAULT NULL, PRIMARY KEY (`orderid`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
-
创建CustomerMapper.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.Mapping.mapper.CustomerMapper"> <resultMap id="getCustomer" type="com.Mapping.entity.Customer"> <id property="customerid" column="customerid"></id> <result property="customername" column="customername"></result> <collection property="orders" ofType="com.Mapping.entity.Orders"> <id property="orderid" column="orderid"></id> <result property="ordername" column="ordername"></result> </collection> </resultMap> <select id="getCustomerById" resultMap="getCustomer" parameterType="Long"> SELECT c.customerid,c.customername,o.orderid,o.ordername FROM tb_customer c,tb_order o WHERE c.customerid = o.customerid and c.customerid=#{id} </select> </mapper>
-
测试
DEBUG [main] - ==> Preparing: SELECT c.customerid,c.customername,o.orderid,o.ordername FROM tb_customer c,tb_order o WHERE c.customerid = o.customerid and c.customerid=? DEBUG [main] - ==> Parameters: 1(Long) DEBUG [main] - <== Total: 4 Customer{customerid=1, customername='客户1', orders=[Orders{orderid=1, ordername='订单1'}, Orders{orderid=2, ordername='订单2'}, Orders{orderid=3, ordername='订单3'}, Orders{orderid=7, ordername='订单7'}]}
在标签中添加子标签标签。
collection标签属性
子元素的属性大部分与元素相同,但其还包含一个特殊属性–ofType 。
ofType:ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型。
多对多
Student(学生)和Course(课程)。 一名学生对应多个课程,一个课程对应多名学生。
-
创建javaBean对象。创建Student和Course类
public class Student { private Integer studentid; private String studentname; private List<Course> courses; } public class Course { private Integer courseid; private String coursename; private List<Student> students; }
-
数据库建表。tb_students和tb_course、tb_students_course表
CREATE TABLE `tb_students` ( `studentid` int(11) NOT NULL AUTO_INCREMENT, `studentname` varchar(255) DEFAULT NULL, PRIMARY KEY (`studentid`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE `tb_course` ( `courseid` int(11) NOT NULL AUTO_INCREMENT, `coursename` varchar(255) DEFAULT NULL, PRIMARY KEY (`courseid`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE `tb_students_course` ( `id` int(11) NOT NULL AUTO_INCREMENT, `student_id` int(11) DEFAULT NULL, `course_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
-
StudentsMapper.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.Mapping.mapper.StudentMapper"> <resultMap id="getStudent" type="com.Mapping.entity.Student"> <id property="studentid" column="studentid"></id> <result property="studentname" column="studentname"/> <collection property="courses" ofType="com.Mapping.entity.Course"> <id property="courseid" column="courseid"/> <result property="coursename" column="coursename"/> </collection> </resultMap> <select id="getStudentById" resultMap="getStudent" parameterType="Integer"> SELECT s.studentid,s.studentname,c.courseid,c.coursename FROM tb_students s ,tb_course c,tb_students_course sc WHERE s.studentid = sc.student_id AND c.courseid = sc.course_id AND s.studentid=#{id} </select> </mapper>
-
测试
DEBUG [main] - ==> Preparing: SELECT s.studentid,s.studentname,c.courseid,c.coursename FROM tb_students s ,tb_course c,tb_students_course sc WHERE s.studentid = sc.student_id AND c.courseid = sc.course_id AND s.studentid=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - <== Total: 3 Student{studentid=1, studentname='学生1', courses=[Course{courseid=1, coursename='语文', students=null}, Course{courseid=3, coursename='英语', students=null}, Course{courseid=4, coursename='物理', students=null}]}
在标签中添加子标签标签。
和一对多(多对一)中类似。