在这一节中,笔者继续向大家介绍有关MyBatis的XML配置文件 。这里一节介绍的内容是比较重要的,也是MyBatis中较为有意思的内容。
在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>的配置。
正如在前面的章节中,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类型储蓄。
在前面的几个章节中,我们学习了MyBatis的XML的配置。主要的目的就是深入了解一份文件 的配置那些参数 是作什么用的。还的我们要重点了解会是typeHandler,这个实际的项目中是很有用的。在本节开始的时候,我们有讲过,除了使用XML配置,我们也可以使用Java的API来配置。下面的章节我们将会讲到。源码下载:https://github.com/owenwilliam/mybatis.com.git