mybaties基础教程之四:SQL语句映射文件(3)

熊孩纸 阅读:585 2021-03-31 23:18:29 评论:0


                    SQL 映射XML 文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如:

<mappers> 
	<mapper resource="com/liming/manager/data/mappers/UserMapper.xml" /> 
	<mapper resource="com/liming/manager/data/mappers/StudentMapper.xml" /> 
	<mapper resource="com/liming/manager/data/mappers/ClassMapper.xml" /> 
	<mapper resource="com/liming/manager/data/mappers/TeacherMapper.xml" /> 
</mappers> 

当Java接口与XML文件在一个相对路径下时,可以不在myBatis配置文件的mappers中声明。

 


SQL 映射XML 文件一些初级的元素:


1. cache – 配置给定模式的缓存
2. cache-ref – 从别的模式中引用一个缓存
3. resultMap – 这是最复杂而却强大的一个元素了,它描述如何从结果集中加载对象
4. sql – 一个可以被其他语句复用的SQL 块
5. insert – 映射INSERT 语句
6. update – 映射UPDATE 语句
7. delete – 映射DELEETE 语句
8. select  -  映射SELECT语句

 


 1.1 resultMap

        resultMap 是MyBatis 中最重要最强大的元素了。你可以让你比使用JDBC 调用结果集省掉90%的代码,也可以让你做许多JDBC 不支持的事。现实上,要写一个等同类似于交互的映射这样的复杂语句,可能要上千行的代码。ResultMaps 的目的,就是这样简单的语句而不需要多余的结果映射,更多复杂的语句,除了只要一些绝对必须的语句描述关系以外,再也不需要其它的。

resultMap属性:type为java实体类;id为此resultMap的标识。

 

 resultMap可以设置的映射:


1. constructor – 用来将结果反射给一个实例化好的类的构造器

a) idArg – ID 参数;将结果集标记为ID,以方便全局调用
b) arg –反射到构造器的通常结果


2. id – ID 结果,将结果集标记为ID,以方便全局调用


3. result – 反射到JavaBean 属性的普通结果


4. association – 复杂类型的结合;多个结果合成的类型

a) nested result mappings – 几resultMap 自身嵌套关联,也可以引用到一个其它上


5. collection –复杂类型集合a collection of complex types


6. nested result mappings – resultMap 的集合,也可以引用到一个其它上


7. discriminator – 使用一个结果值以决定使用哪个resultMap

a) case – 基本一些值的结果映射的case 情形

i. nested result mappings –一个case 情形本身就是一个结果映射,因此也可以包括一些相同的元素,也可以引用一个外部resultMap。

 

 

1.1.1 id、result

id、result是最简单的映射,id为主键映射;result其他基本数据库表字段到实体类属性的映射。
  最简单的例子:

<?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.student.dao"> 	 
 	<resultMap type="Classes" id="classesAllResultMap"> 
 		<id property="cid" column="cid"/> 
 		<result property="cname" column="cname"/> 
 		<result property="teacher" column="teacher"/> 		 
 	</resultMap>    
 </mapper>

id、result语句属性配置细节:

 

属性

描述

 

property

需要映射到JavaBean的属性名称。

 

column

数据表的列名或者标签别名。

 

javaType

一个完整的类名,或者是一个类型别名。如果你匹配的是一个JavaBean,那MyBatis通常会自行检测到。然后,如果你是要映射到一个HashMap,那你需要指定javaType要达到的目的。

 

jdbcType

数据表支持的类型列表。这个属性只在insert,update或delete 的时候针对允许空的列有用。JDBC需要这项,但MyBatis 不需要。如果你是直接针对JDBC编码,且有允许空的列,而你要指定这项。

 

typeHandler

使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。

 

 

 

支持的JDBC类型
       为了将来的引用,MyBatis 支持下列JDBC 类型,通过JdbcType 枚举:
BIT,FLOAT,CHAR,TIMESTAMP,OTHER,UNDEFINED,TINYINT,REAL,VARCHAR,BINARY,BLOB,NVARCHAR,SMALLINT,DOUBLE,LONGVARCHAR,VARBINARY,CLOB,NCHAR,INTEGER,NUMERIC,DATE,LONGVARBINARY,BOOLEAN,NCLOB,BIGINT,DECIMAL,TIME,NULL,CURSOR

 

 

1.1.2 constructor

我们使用id、result时候,需要定义java实体类的属性映射到数据库表的字段上。这个时候是使用JavaBean实现的。当然我们也可以使用实体类的构造方法来实现值的映射,这个时候是通过构造方法参数的书写的顺序来进行赋值的。 使用construcotr功能有限(例如使用collection级联查询)。

上面使用id、result实现的功能就可以改为:

<resultMap type="Classes" id="classesAllResultMap"> 
 	    <idArg javaType="int" column="cid"/>   
        <arg javaType="String" column="cname"/>   
        <arg javaType="String" column="teacher"/> 	      
 	</resultMap> 


  当然,我们需要定义Classes实体类的构造方法:

package com.student.classes; 
 
import java.io.Serializable; 
import java.util.Date; 
import java.util.List; 
 
import com.student.dao.Student; 
 
public class Classes implements Serializable { 
 
	/** 
	 *  
	 */ 
	private static final long serialVersionUID = 1L; 
	 
	private int cid;   
	private String cname;   
    private String teacher; 
     
	public int getCid() { 
		return cid; 
	} 
	public void setCid(int cid) { 
		this.cid = cid; 
	} 
	public String getCname() { 
		return cname; 
	} 
	public void setCname(String cname) { 
		this.cname = cname; 
	} 
	public String getTeacher() { 
		return teacher; 
	} 
	public void setTeacher(String teacher) { 
		this.teacher = teacher; 
	}	 
	 
	//classes 构造函数 
	public Classes(int cid, String cname, String teacher) { 
		super(); 
		this.cid = cid; 
		this.cname = cname; 
		this.teacher = teacher; 
	} 
} 

1.1.3 association联合

联合元素用来处理“一对一”的关系。需要指定映射的Java实体类的属性,属性的javaType(通常MyBatis 自己会识别)。对应的数据库表的列名称。如果想覆写的话返回结果的值,需要指定typeHandler。
不同情况需要告诉MyBatis 如何加载一个联合。MyBatis 可以用两种方式加载:

1. select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活;
2. resultsMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。

第一步:创建实体对象Classes类和Studentl类

package com.student.classes; 
 
import java.io.Serializable; 
import java.util.Date; 
import java.util.List; 
 
import com.student.dao.Student; 
 
public class Classes implements Serializable { 
 
	/** 
	 *  
	 */ 
	private static final long serialVersionUID = 1L;	 
	private int cid;   
	private String cname;   
    private String teacher;     
	public int getCid() { 
		return cid; 
	} 
	public void setCid(int cid) { 
		this.cid = cid; 
	} 
	public String getCname() { 
		return cname; 
	} 
	public void setCname(String cname) { 
		this.cname = cname; 
	} 
	public String getTeacher() { 
		return teacher; 
	} 
	public void setTeacher(String teacher) { 
		this.teacher = teacher; 
	} 
} 

student.class类文件

package com.student.dao; 
 
import java.io.Serializable; 
import java.util.Date; 
 
import com.student.classes.Classes; 
 
public class Student implements Serializable { 
 
	/** 
	 *  
	 */ 
	private static final long serialVersionUID = 1L; 
	 
	private int sid;   
	private String sname;   
	private String major;   
	private Date birth;   
	private float score;   
	private int cid;   
	private int status;	 
	private Classes classes;//实现resultMap 的association标签功能	 
	 
	public Classes getClasses() { 
		return classes; 
	} 
	public void setClasses(Classes classes) { 
		this.classes = classes; 
	} 
	public int getSid() { 
		return sid; 
	} 
	public void setSid(int sid) { 
		this.sid = sid; 
	} 
	public String getSname() { 
		return sname; 
	} 
	public void setSname(String sname) { 
		this.sname = sname; 
	} 
	public String getMajor() { 
		return major; 
	} 
	public void setMajor(String major) { 
		this.major = major; 
	} 
	public Date getBirth() { 
		return birth; 
	} 
	public void setBirth(Date birth) { 
		this.birth = birth; 
	} 
	public float getScore() { 
		return score; 
	} 
	public void setScore(float score) { 
		this.score = score; 
	} 
	public int getCid() { 
		return cid; 
	} 
	public void setCid(int cid) { 
		this.cid = cid; 
	} 
	public int getStatus() { 
		return status; 
	} 
	public void setStatus(int status) { 
		this.status = status; 
	}   
}

StudentMapper.xml文件和ClassMapper.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.student.dao"> 	 
 	<resultMap type="Classes" id="classesAllResultMap"> 
 		<id property="cid" column="cid"/> 
 		<result property="cname" column="cname"/> 
 		<result property="teacher" column="teacher"/> 		 
 	</resultMap>  	 
 </mapper>


<?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.student.dao"> 
 	 
 	<resultMap type="Student" id="studentAllResultMap"> 
 		<id property="sid" column="SID"/> 
 		<result property="sname" column="SNAME"/> 
 		<result property="major" column="MAJOR"/> 
 		<result property="birth" column="BIRTH"/> 
 		<result property="score" column="SCORE"/> 
 		<result property="cid" column="CID"/> 
 		<result property="status" column="STATUS"/> 		 
 		<association property="classes" column="cid"  resultMap="classesAllResultMap"/> 
 	</resultMap>	  
  
   <select id="getClassAndTeacher" parameterType="int" resultMap="studentAllResultMap">   
   SELECT *   
      FROM student CT LEFT JOIN classes TT ON CT.cid = TT.cid   
    WHERE CT.cid = #{id};   
</select>     
 </mapper> 


经过上面代码的编写----进入我们今天做重要的环节(结果展示)

package com.mybaties.test; 
 
import java.io.IOException; 
import java.io.Reader; 
import java.util.Iterator; 
import java.util.List; 
 
 
 
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 com.mybaties.entry.User; 
import com.mybaties.entry.UserInterface; 
import com.student.dao.Student; 
 
public class Test { 
	 
	/** 
	 * @param 测试方法 
	 */ 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		 SqlSession session = null; 
		try { 
		    String resource = "Configuration.xml"; 
	        Reader reader= Resources.getResourceAsReader(resource);				 
	        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 
	        SqlSessionFactory factory = builder.build(reader);	         
	        session = factory.openSession();	         
	        List<Student> list=session.selectList("com.student.dao.getClassAndTeacher", 1001);   
	        for(int i=0;i<list.size();i++){ 
	        	Student student=list.get(i); 
	        	System.out.println("相关用户信息:"+student.getCid()+"\r\n"+student.getSname()+"\r\n"+student.getClasses().getCid()+"\r\n"+student.getClasses().getCname()); 
	        } 
	   
		} catch (IOException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
		 
		 session.commit(); 
		 session.close(); 
	} 
}

结果展示:

1.1.4 collection聚集

聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
不同情况需要告诉MyBatis 如何加载一个聚集。MyBatis 可以用两种方式加载:

1. select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活;
2. resultsMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。

 

例如,一个班级有多个学生。
首先定义班级中的学生列表属性:

private List<StudentEntity> studentList;

1.1.4.1使用select实现聚集

 用法和联合很类似,区别在于,这是一对多,所以一般映射过来的都是列表。所以这里需要定义javaType为ArrayList,还需要定义列表中对象的类型ofType,以及必须设置的select的语句名称(需要注意的是,这里的查询student的select语句条件必须是外键classID)。

 

ClassMapper.xml文件部分内容:

<resultMap type="ClassEntity" id="classResultMap"> 
	<id property="classID" column="CLASS_ID" /> 
	<result property="className" column="CLASS_NAME" /> 
	<result property="classYear" column="CLASS_YEAR" /> 
	<association property="teacherEntity" column="TEACHER_ID"  select="getTeacher"/> 
	<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" select="getStudentByClassID"/> 
</resultMap> 
 
<select id="getClassByID" parameterType="String" resultMap="classResultMap"> 
	SELECT * FROM CLASS_TBL CT 
	WHERE CT.CLASS_ID = #{classID}; 
</select> 

StudentMapper.xml文件部分内容:

<!-- java属性,数据库表字段之间的映射定义 --> 
<resultMap type="StudentEntity" id="studentResultMap"> 
	<id property="studentID" column="STUDENT_ID" /> 
	<result property="studentName" column="STUDENT_NAME" /> 
	<result property="studentSex" column="STUDENT_SEX" /> 
	<result property="studentBirthday" column="STUDENT_BIRTHDAY" /> 
</resultMap> 
 
<!-- 查询学生list,根据班级id --> 
<select id="getStudentByClassID" parameterType="String" resultMap="studentResultMap"> 
	<include refid="selectStudentAll" /> 
	WHERE ST.CLASS_ID = #{classID} 
</select> 

1.1.4.2使用resultMap实现聚集

 使用resultMap,就需要重写一个sql,left join学生表。

<resultMap type="ClassEntity" id="classResultMap"> 
	<id property="classID" column="CLASS_ID" /> 
	<result property="className" column="CLASS_NAME" /> 
	<result property="classYear" column="CLASS_YEAR" /> 
	<association property="teacherEntity" column="TEACHER_ID"  resultMap="teacherResultMap"/> 
	<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" resultMap="studentResultMap"/> 
</resultMap> 
 
<select id="getClassAndTeacherStudent" parameterType="String" resultMap="classResultMap"> 
	SELECT * 
	  FROM CLASS_TBL CT 
	       LEFT JOIN STUDENT_TBL ST 
	          ON CT.CLASS_ID = ST.CLASS_ID 
	       LEFT JOIN TEACHER_TBL TT 
	          ON CT.TEACHER_ID = TT.TEACHER_ID 
	  WHERE CT.CLASS_ID = #{classID}; 
</select> 


其中的teacherResultMap请见上面TeacherMapper.xml文件部分内容中。studentResultMap请见上面StudentMapper.xml文件部分内容中。


1.1.5discriminator鉴别器

 

有时一个单独的数据库查询也许返回很多不同(但是希望有些关联)数据类型的结果集。鉴别器元素就是被设计来处理这个情况的,还有包括类的继承层次结构。鉴别器非常容易理解,因为它的表现很像Java语言中的switch语句。

定义鉴别器指定了column和javaType属性。列是MyBatis查找比较值的地方。JavaType是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)。

下面这个例子为,当classId为20000001时,才映射classId属性。

<resultMap type="liming.student.manager.data.model.StudentEntity" id="resultMap_studentEntity_discriminator"> 
	<id 	property="studentId" 		column="STUDENT_ID" javaType="String" jdbcType="VARCHAR"/> 
	<result property="studentName" 		column="STUDENT_NAME" javaType="String" jdbcType="VARCHAR"/> 
	<result property="studentSex" 		column="STUDENT_SEX"  javaType="int" jdbcType="INTEGER"/> 
	<result property="studentBirthday" 	column="STUDENT_BIRTHDAY"  javaType="Date" jdbcType="DATE"/> 
	<result property="studentPhoto" 	column="STUDENT_PHOTO" javaType="byte[]" jdbcType="BLOB" typeHandler="org.apache.ibatis.type.BlobTypeHandler" /> 
	<result property="placeId" 			column="PLACE_ID" javaType="String" jdbcType="VARCHAR"/> 
	<discriminator column="CLASS_ID" javaType="String" jdbcType="VARCHAR"> 
		<case value="20000001" resultType="liming.student.manager.data.model.StudentEntity" > 
			<result property="classId" column="CLASS_ID" javaType="String" jdbcType="VARCHAR"/> 
		</case> 
	</discriminator> 
</resultMap> 



声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号