在这一节中,笔者继续向大家介绍有关MyBatis的XML配置文件 。这里一节介绍的内容是比较重要的,也是MyBatis中较为有意思的内容。
1. typeAliases的参数
在SQL的映射文件的配置中,我们需要在resultType和parameterType的属性中,给出完整的限定名的JavaBean对象。如下所示:
<select id="findStudentById" parameterType="int"
resultType=" com.owen.mybatis.domain.Student">
SELECT STUD_ID AS ID, NAME, EMAIL, DOB
FROM STUDENTS WHERE STUD_ID=#{Id}
</select>
<update id="updateStudent" parameterType="com.owen.mybatis.domain.
Student">
UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob}
WHERE STUD_ID=#{id}
</update>
上面的代码中,可以看到我们给出了完整的限定名com.owen.mybatis.Student的对象,配置在resultType和parameterType属性中。
如果我们每次都写出同样的完整限制名,而又是一样的,这样会很麻烦。所以我们可以定义个别名,运用别名来使用到任何地方。具体的使用如下。
<typeAliases>
<typeAlias alias="Student" type="com.owen.mybatis.domain.Student"/>
<typeAlias alias="Tutor" type="com.owen.mybatis.domain.Tutor"/>
<package name="com.owen.mybatis.domain"/>
</typeAliases>
现在我们在SQL的映射文件中,就可以如下的定义了:
<select id="findStudentById" parameterType="int" resultType="Student">
SELECT STUD_ID AS ID, NAME, EMAIL, DOB
FROM STUDENTS WHERE STUD_ID=#{id}
</select>
<update id="updateStudent" parameterType="Student">
UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob}
WHERE STUD_ID=#{id}
</update>
取而代之的是我们为JavaBean定义的别名,不过你也可以直接定义包名,MyBatis就会去扫描包下的所有的类,并且以类名来注册到容器中。就像下面所示的,那么使用时一样的运用Student.
<typeAliases>
<package name="com.owen.mybatis.domain"/>
</typeAliases>
如果这里有Student.java和Tutor.java的JavaBean在包com.owen.mybatis.domain的包内,那么com.owen.mybatis.domain.Student以student名注册,而com.owen.mybatis.domain.Tutor以tutor注册。不过笔者试过了,我们使用时,首个字母的大小写是不区分的。如下的例子所示:
<typeAliases>
<typeAlias alias="Student" type="com.owen.mybatis.domain.Student"/>
<typeAlias alias="Tutor" type="com.owen.mybatis.domain.Tutor"/>
<package name="com.owen.mybatis.domain"/>
<package name="com.owen.mybatis.webservices.domain"/>
</typeAliases>
当然,我们还可以用其它的方法来命名别名,那就是应用注解@Alias.
@Alias("StudentAlias")
public class Student
{ }
需要注意的是,如果你即使用了@Alias又使用了<typeAliases>,那么将会取@Alias的别名。也就是@Alias会覆盖<typeAliases>的配置。
2. typeHandlers的参数
正如在前面的章节中,MyBatis简化了持久性逻辑通过抽象JDBC实现。MyBatis使用JDBC引擎,提供简单的方法来实现数据库操作。
当我们应用MyBatis执行一个INSERT的操作时, 我们会向java的对象放入一些参数,MyBatis将会创建一个PrepareStatrement和放入参数的值,那些占位符的参数,将会转换为setXXX()的方法。这里所说的XXX可以是Int,String,Date等,这些是Javar基础属性。如下例子。
<insert id="insertStudent" parameterType="Student">
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)
VALUES(#{studId},#{name},#{email},#{dob})
</insert>
为了去执行上面的语句,MyBatis将会执行下面的步骤。
1) 创建一个PreparedStatement的接口,运用占位符如下:
PreparedStatement pstmt = connection.prepareStatement
("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(?,?,?,?)");
1) 在Student的对象中查找studId的属性,和应用setXXX的方法放入值。这里studId是Integer的类型,所以将会用setInt()的方法。
pstmt.setInt(1,student.getStudId());
1) 相似的,name和email的属性在MyBatis中会使用setString()的方法。
pstmt.setString(2, student.getName());
pstmt.setString(3, student.getEmail());
1) 关于dob的属性,MyBatis将会使用setDate()r的方法放入dob的值。
2) MyBatis首先会使用java.util.Date的转换器,转换为java.sql.Timestamp和放入值。
pstmt.setTimestamp(4, new Timestamp((student.getDob()).
getTime()));
酷!但是MyBatis是如何知道 Integer是使用setInt()方法,String的是使用setString()方法呢?其实MyBatis确定这些也是使用typehandlers。
MyBatis内置了样式处理器,这个处理器可以处理的样式有:byte[],java.util.Date,java.sql.Date,java.sql.Time,java.sql.Timestamp,javaenums等。只要遇到这些定义的参数,Mabatis就会支执行PreparedStatement的类。但是要是我们给出了一个对象的类型呢?那么MyBatis要怎么处理呢?
如下面呈现的,我们在STUDENT的表添加了PHONE的字段,Student拥有phonenuber的参数,所以我们定义个PhoneNumber的类。
public class PhoneNumber
{
private String countryCode;
private String stateCode;
private String number;
public PhoneNumber() {
}
public PhoneNumber(String countryCode, String stateCode, String
number) {
this.countryCode = countryCode;
this.stateCode = stateCode;
this.number = number;
}
public PhoneNumber(String string) {
if(string != null){
String[] parts = string.split("-");
if(parts.length>0) this.countryCode=parts[0];
if(parts.length>1) this.stateCode=parts[1];
if(parts.length>2) this.number=parts[2];
}
}
public String getAsString() {
return countryCode+"-"+stateCode+"-"+number;
}
// Setters and getters
}
public class Student
{
private Integer id;
private String name;
private String email;
private PhoneNumber phone;
// Setters and getters
}
<insert id="insertStudent" parameterType="Student">
insert into students(name,email,phone)
values(#{name},#{email},#{phone})
</insert>
这里,我们给phone参数传入的值是#{phone},这里的phone对象其实就是PhoneNumber。然而,MyBatis并不知道如何去操作它。
为了让MyBatis知道 如何去操作这个对象,像phoneNumber,我们需要创建一个操作的执行类型,如下步骤:
1) MyBatis提供一个抽象的类BaseTypeHandler<T>,我们可以去继承它,创建用户的类型转换器。
importjava.sql.CallableStatement;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importorg.apache.ibatis.type.BaseTypeHandler;
importorg.apache.ibatis.type.JdbcType;
importcom.owen.mybatis.domain.PhoneNumber;
public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>
{
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
PhoneNumber parameter, JdbcType jdbcType) throws
SQLException {
ps.setString(i, parameter.getAsString());
}
@Override
public PhoneNumber getNullableResult(ResultSet rs, String
columnName)
throws SQLException {
return new PhoneNumber(rs.getString(columnName));
}
@Override
public PhoneNumber getNullableResult(ResultSet rs, int
columnIndex)
throws SQLException {
return new PhoneNumber(rs.getString(columnIndex));
}
@Override
public PhoneNumber getNullableResult(CallableStatement cs, int
columnIndex)
throws SQLException {
return new PhoneNumber(cs.getString(columnIndex));
}
}
2) 我们使用ps.setString()和rs.getString()的方法,因为phone的数值是VARCHAR的类型。
3) 一旦我们的操作类创建了,我们需要在mybatis-config.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>
<properties resource="application.properties"/>
<typeHandlers>
<typeHandler handler="com.owen.mybatis.typehandlers.
PhoneTypeHandler"/>
</typeHandlers>
</configuration>
之后,我们注册了PhoneTypeHandler,MyBatis将会有能力去处理Phone类型的对象,将对象以VARCHAR类型储蓄。
3.总结
在前面的几个章节中,我们学习了MyBatis的XML的配置。主要的目的就是深入了解一份文件 的配置,那些参数是什么作用的。还的我们要重点了解会是typeHandler,这个实际的项目中是很有用的。在本节开始的时候,我们有讲过,除了使用XML配置,我们也可以使用Java的API来配置。下面的章节我们将会讲到。源码下载:https://github.com/owenwilliam/mybatis.com.git