Mybatis 坑路3 -> 基于 XML 配置映射器

这篇博客详细介绍了MyBatis中基于XML配置的映射器,包括映射器配置文件与接口的关联、INSERT、UPDATE、DELETE和SELECT语句的配置方法,重点解析了ResultMap的使用,包括结果集映射到Map、一对一和一对多映射的实现。通过实例展示了MyBatis如何简化SQL操作并提高代码的可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于 XML 配置映射器

映射器配置文件和映射器接口

INSERT 语句

UPDATE 语句

DELETE 语句

SELECT 语句

结果集映射 ResultMap

拓展 ResultMap

一对一映射

一对多映射

基于 XML 配置映射器

  关系型数据库和 SQL 是经受时间考研和验证的数据存储机制。和其他的 ORM 框架如 Hibernate 不同,MyBatis 鼓励开发者考研直接使用数据库,而不是将其对开发者隐蔽,因为这样考研充分发挥数据库服务器所提供的 SQL 语句的巨大威力。与此同时,MyBatis 消除了书写大量冗余代码的痛苦,它让使用 SQL 更容易。
  在代码里直接嵌套 SQL 语句是很差的编码实践,并且维护起来困难。MyBatis 使用了映射器配置文件或注解来配置 SQL 语句。在以下的学习中,我们会看到具体怎样使用映射器配置文件来配置映射器 SQL 语句。

映射器配置文件和映射器接口

  在 xx.mybatis3.mappers 包中的 StudentMapper.xml 配置文件内,配置 id 为 “findStudentById” 的 SQL 语句:

<?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="xx/mybatis3.mappers.StudentMapper">
	<select id="findStudentById" parameterType="int" resultType="Student">
		select stud_id as studid,name,email,dob from Students where stud_id = #{studId}
	</select>
</mapper>

通过下列代码调用 findStudentById 映射的 SQL 语句:

public Student findStudentById(Integer studId){
	SqlSession sqlSession = MyBatisUtil.getSqlSession();
	try{
		Student student = sqlSession.selectOne("xx.mybatis3.mappers.StudentMapper.findStudentById",studId);
		return student;
	} finally {
		sqlSession.close();
	}
}

INSERT 语句

  MyBatis 提供了多种元素来配置不同类型的语句,如 SELECT,INSERT,UPDATE,DELETE。接下来让我们看看如何具体配置映射语句:

INSERT 语句:

<insert id="insertStudent" parameterType="Student">
	INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,PHONE) VALUES(#{studId},#{name},#{email},#{phone})
</insert>

  在上述的 INSERT 语句中,我们为可以自动生成(auto-generated)主键的列 STUD_ID 插入值。我们可以使用 useGeneratedKeys 和 keyProperty 属性让数据库生成 auto_increment 列的值,并将生成的值设置到其中一个输入对象属性内,如下所示:

<insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId">
	INSERT INTO STUDENTS(NAME,EMAIL,PHONE) VALUES (#{name},#{email},#{phone})
</insert>

  这里 STUD_ID 列值将会被 MySQL 数据库自动生成,并且生成的值会被设置到 student 对象的 studId 属性上。
  有些数据库如 Oracle 并不支持 AUTO_INCREMENT 列,其使用序列(SEQUENCE)来生成主键值。
  假设我们有一个名为 STUD_ID_SEQ 的序列来生成 SUTD_ID 主键值。使用如下代码来生成主键:

<insert id="insertStudent" parameterType="Student">
	<selectKey keyProperty="studId" resultType="int" order="BEFORE">
		SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL
	</seleectKey>
	INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,PHONE) VALUES (#{studId},#{name},#{email},#{phone})
</insert>

  这里我们使用了 <selectKey>子元素来生成主键值,并将值保存到 Student 对象的 studId 属性上。属性 order=“before” 表示 Mybatis 将取得序列的下一个值作为主键值,并且在执行 INSERT SQL 语句之前将值设置到 studId 属性上。

UPDATE 语句

<update id="updateStudent" parameterType="Student">
	UPDATE STUDENTS SET NAME=#{name},EMAIL=#{email},PHONE=#{phone} WHERE STUD_ID = #{studId}
</update>

DELETE 语句

<delete id="deleteStudent" parameterType="int">
	DELETE FROM STUDENTS WHERE STUD_ID = #{studId}
</delete>

SELECT 语句

  MyBatis 真正强大的功能,在于映射 SELECT 查询结果 JavaBeans 方面的极大灵活性。

<select id="findStudentById" parameterType="int" resultType="Student">
	SELECT STUD_ID,NAME,EMAIL,PHONE FROM STUDENTS WHERE STUD_ID = #{studId}
</select>

  如果检查 Student 对象的属性值,你会发现 studId 属性值并没有被 stud_id 列值填充。这是因为 MyBatis 自动对 JavaBean 中属性名匹配的别名:

SELECT STUD_ID AS STUDID

SQL 语句

  通过 SQL 标签定义的语句可以被其他语句通过 include 进行引用。在不同引用情况下可以传递不同的参数,例如:

<sql id="userColumns">${alias}.id,${alias}.username,${alias}.password</sql>
<select id="selectUsers" resultType="map">
	select
	<include refid="userColumns"><property name="alias" value="t1"/></include>,
	<include refid="userColumns"><property name="alias" value="t2"/></include>
	from some_table t1 left join some_table t2 on t1.id=t2.id
</select>

Sql 标签也可以被嵌套使用,如:

SQL语句

<sql id="sometable">
	${prefix} Table
</sql>
<sql id="someinclude">
	from <include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
	select field1,field2,field3
	<include refid="someinclude">
		<property name="prefix" value="Some"/>
		<property name="include_target" value="sometable"/>
	</include>
</select>

结果集映射 ResultMap

  ResultMap 被用来将 SQL SELECT 语句的结果集映射到 JavaBeans 的属性中。我们可以定义结果集映射 ResultMap 并且在一些 SELECT 语句上引用 resultMap。MyBatis 的结果集映射 ResultMap 特性非常强大,可以使用它降简单的 SELECT 语句映射到复杂的一对一和一对多关系的 SELECT 语句上。
一个简单的 ResultMap:

<resultMap id="StudentResult" type="xx.mybatis3.domain.Student">
	<id property="studId" column="stud_id">
	<result property="name" column="name" />
	<result property="email" column="email" />
	<result property="phone" column="phone" />
</resultMap>
<select id="findAllStudents" resultMap="StudentResult">
	SELECT * FROM STUDENTS
</select>
<select id="findStudentById" parameterType="int" resultMap="StudentResult">
	SELECT * FROM STUDENTS WHERE STUD_ID = #{studId}
</select>

resultType 和 resultMap 二者只能用其一,不能同时使用。

将结果集映射到 Map

1、sqlMapper.xml 文件的配置

<select id="findStduentById" parameterType="int" resultType="map">

2、Mapper 接口方法定义:

Map<String,Object> findStudentById(Integer stuId);
如果 resultType="map",返回多行结果,则方法中的返回值类型为 List<Map<String,Obejct>>

拓展 ResultMap

  我们可以从另外一个<resultMap>,拓展出一个新的<resultMap>,这样,原先的属性映射可以继承过来

<resultMap type="Student" id="StudentResult">
	<id property="studId" column="stud_id" />
	<result property="name" column="name" />
	<result property="email" column="email" />
	<result property="phone" column="phone" />
</resultMap>
<resultNap type="Student" id="StudentWithAddressResult" extends="StudentResult">
	<result property="address.addrId" column="addr_id" />
	<result property="address.street" column="street" />
	<result property="address.city" column="city" />
</resultMap>

一对一映射

  每一个学生都有一个与之关联的地址信息。表 STUDENTS 有一个 ADDR_ID 列,是 ADDRESSES 表的外键。

public class Address{
	private Integer addrId;
	private String street;
	private String city;
	private String state;
	private String zip;
	private String country;
}

public class Student{
	private Integer studId;
	private String name;
	private String email;
	private String phone;
	private Address address;
}

<resultMap type="Student" id="StudentWithAddressResult">
	<id property="studId" column="stud_id" />
	<result property="name" column="name" />
	<result property="email" column="email" />
	<result property="phone" column="phone" />
	<result property="address.addrId" column="addr_id" />
	<result property="address.street" column="street" />
	<result property="address.city" column="city" />
	<result property="address.state" column="state" />
	<result property="address.zip" column="zip" />
	<result property="address.cuontry" column="country" />
</resultMap>

<select id="selectStudentWithAddress" parameterType="int" resultMap="StudentWithAddressResult">
	SELECT STUD_ID,NAME,EMAIL,A.ADDR_ID,STREET,CITY,STATE,ZIP,COUNTRY FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID WHERE STUD_ID=#{studId}
</select>

  我们可以使用圆点记法为内嵌的对象的属性赋值。在上述的 resultMap 中,Student 的 address 属性使用了圆点记法被赋上了 address 对应列的值。同样地,我们可以访问任意深度的内嵌对象的属性。
  使用一个嵌套结果 ResultMap 方式来获取 Student 及其 Address 信息:

<resultMap type="Address" id="AddressResult">
	<id property="addrId" column="addr_id" />
	<result property="street" column="street" />
	<result property="city" column="city" />
	<result property="state" column="state" />
	<result property="zip" column="zip" />
	<result property="country" column="country" />
</resultMap>
<resultMap type="Student" id="StudentWithAddressResult">
	<id property="studId" column="stud_id" />
	<result property="name" column="name" />
	<result property="email" column="rmail" />
	<association property="address" resultMap="AddressResult" />
</resultMap>

  元素<association>被用来导入"有一个"(has-one)类型的关联。在上述的例子中,我们使用了<association>元素引用了另外一个在同一个 XML 文件中定义的 <resultMap>。我们也可以使用<association>定义内嵌的 resultMap:

<resultMap type="Student" id="StudentWithAddressResult">
	<id property="studId" column="stud_id" />
	<result property="name" column="name" />
	<result property="email" column="email" />
	<association property="address" javaType="Address">
		<id property="addrId" column="addr_id" />
		<result property="street" column="street" />
		<result property="city" column="city" />
		<result property="state" column="state" />
		<result property="zip" column="zip" />
		<result property="country" column="country" />
	</association>
</resultMap>

  可以通过使用嵌套 select 查询来获取 Student 及其 Address 信息:

<resultMap type="Address" id="AddressResult">
	<id property="addrId" column="addr_id" />
	<result property="street" column="street" />
	<result property="city" column="city" />
	<result property="state" column="state" />
	<result property="zip" column="zip" />
	<result property="country" column="country" />
</resultMap>
<select id="findAddressById" parameterType="int" resultMap="AddressResult">
	SELECT * FROM ADDRESSES WHERE ADDR_ID=#{id}
</select>

<resultMap type="Student" id="StudentWithAddressResult">
	<id property="studId" column="stud_id" />
	<result property="name" column="name" />
	<result property="email" column="email" />
	<association property="address" column="addr_id" select="findAddressById" />
</resultMap>
<select id="findStudentWithAddress" parameterType="int"
resultMap="StudentWithAddressResult">
	SELECT * FROM STUDENTS WHERE STUD_ID=${id}
</select>

  在此方式中,<association>元素的 select 属性被设置成了 id 为 findAddressById 的语句。这里,两个分开的 SQL 语句将会在数据库中执行,第一个调用 findStudentById 加载 student 信息,而第二个调用 findAddressById 来加载 address 信息。

一对多映射

  使用<collection>元素将一对多类型的结果映射到一个对象集合上。
  和一对一映射一样,我们可以使用嵌套结果 ResultMap 和嵌套 Select 语句两种方式映射实现一对多映射。
嵌套结果 ResultMap:

<collection property="course" resultMap="CourseResult" />

嵌套 Select 语句:

<collection property="courses" column="tutor_id" select="findCoursesByTutor" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值