标签:
MyBatis 的配置文件即mybatis-config.xml中的configuration标签下有settings、properties等属性。本文对其中常用属性的配置做简单介绍
properties 属性可以从properties文件中获得,也可以直接写到配置文件中。
属性文件里config.properties中内容为
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=root
配置文件mybatis-config.xml中有这样的内容
<!-- properties配置 -->
<properties resource="config.properties">
<property name="username" value="shisong"/>
<property name="password" value="123456"/>
</properties>
<!-- properties使用 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
上面例子中的password重复指定了且不一样,而数据库的正确密码是root,上面的例子是能够成功的; 当把配置中的password改为root,而把porperties中password改为123456时则会失败; 所以当属性在不只一个地方进行了配置时,要有一个加载顺序,后加载的会覆盖先加载的。
另外属性加载的时候,还可以通过SqlSessionBuilder.build()方法来加载
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);
当属性在不只一个地方进行了配置时,加载顺序是这样的
XML文件中在properties元素体内property标签指定的属性resource或url指定的资源文件中的属性,并覆盖已读取的同名属性类型别名是为Java类型命名的一个短的名字,意义仅在于用来减少类完全限定名的冗余。
可以像下面这样起别名:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
也可以指定一个包名, MyBatis 会在包名下搜索需要的 Java Bean,比如:
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
包 domain.blog 中所有的的 Java Bean,在没有注解的情况下,会使用 Bean 的类名来作为它的别名。 比如 domain.blog.Author 的别名为 Author(大小写不敏感);若有注解,则别名为其注解值。如下:
@Alias("author")
public class Author {
...
}
MyBatis 已经为普通的 Java 类型内建了许多相应的类型别名,它们都是大小写不敏感的。
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean //以上都是原始类型
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator
数据库中的类型和Java的类型是不一样的,但是有一定的对应关系。
无论是 MyBatis 在预处理语句(PreparedStatement)中设置参数时,还是从结果集中取出值时,都会用类型处理器以合适的方式进行转换。 typeHandler就是进行jdbcType和javaType之间的转换的。
MyBatis已经自动注册了一些TypeHandler,我们仍然可以写自己的TypeHandler,具体方法是:实现org.apache.ibatis.type.TypeHandler接口,或继承org.apache.ibatis.type.BaseTypeHandler抽象类并实现其中的抽象方法,然后指明自己的TypeHandler是哪个jdbcType和javaType之间的转换。
推荐使用BaseTypeHandler,因为它对null值进行了过滤,而且它继承了TypeReference抽象类,通过TypeReference的getRawType()方法可以获取到当前TypeHandler所使用泛型的原始类型。这对Mybatis在注册TypeHandler的时候是非常有好处的。在没有指定javaType的情况下,Mybatis在注册TypeHandler时可以通过它来获取当前TypeHandler所使用泛型的原始类型作为要注册的TypeHandler的javaType类型。
假设有一个User类,其中有一个属性interests是String数组类型
public class User {
private int id;
private String name;
private int age;
private String[ ] interests;
...
}
要为String 数组定义一个转换类StringArrayTypeHandler
// StringArrayTypeHandler.java
@MappedJdbcTypes(JdbcType.VARCHAR)
public class StringArrayTypeHandler extends BaseTypeHandler<String[ ]> {
/**
* 用于定义在Mybatis设置参数时该如何把Java类型的参数转换为对应的数据库类型
* @param ps 当前的PreparedStatement对象
* @param i 当前参数的位置
* @param parameter 当前参数的Java对象
* @param jdbcType 当前参数的数据库类型
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String[ ] parameter, JdbcType jdbcType) throws SQLException {
//由于BaseTypeHandler中已经把parameter为null的情况做了处理,所以这里我们就不用再判断parameter是否为空了,直接用就可以了
StringBuffer result = new StringBuffer();
for (String value : parameter)
result.append(value).append(",");
result.deleteCharAt(result.length()-1);
ps.setString(i, result.toString());
}
}
/**
* 用于在Mybatis获取数据结果集时如何把数据库类型转换为对应的Java类型
* @param rs 当前的结果集
* @param columnName 当前的字段名称
* @return 转换后的Java对象
* @throws SQLException
*/
@Override
public String[ ] getNullableResult(ResultSet rs, String columnName) throws SQLException {
return this.getStringArray(rs.getString(columnName));
}
/**
* 用于在Mybatis通过字段位置获取字段数据时把数据库类型转换为对应的Java类型
* @param rs 当前的结果集
* @param columnIndex 当前字段的位置
* @return 转换后的Java对象
* @throws SQLException
*/
@Override
public String[ ] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return this.getStringArray(rs.getString(columnIndex));
}
/**
* 用于Mybatis在调用存储过程后把数据库类型的数据转换为对应的Java类型
* @param cs 当前的CallableStatement执行后的CallableStatement
* @param columnIndex 当前输出参数的位置
* @return
* @throws SQLException
*/
@Override
public String[ ] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return this.getStringArray(cs.getString(columnIndex));
}
private String[ ] getStringArray(String columnValue) {
if (columnValue == null)
return null;
return columnValue.split(",");
}
}
MyBatis 在TypeHandlerRegistry类中已经注册了许多TypeHandler。
我们建立了自己的TypeHandler之后就需要把它注册到Mybatis的配置文件中,让Mybatis能够识别并使用它。注册TypeHandler主要有两种方式:
handler来指明当前要注册的TypeHandler的全名称。另外还有两个可选属性,一个是javaType,用以指定对应的java类型;另一个是jdbcType,用以指定对应的jdbc类型。<!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.StringArrayTypeHandler" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>
</typeHandlers>
注意上面的javaType要写全类名,String[]的全类名为"[Ljava.lang.String;",所以上面注册的javaType属性为javaType="[Ljava.lang.String;"
TypeHandler。<!-- mybatis-config.xml -->
<typeHandlers>
<package name="org.mybatis.example"/>
</typeHandlers>
总结
MyBatis会通过窥探属性的原始类型来推断由类型处理器处理的 Java 类型(前面说的getRawType()方法),可以通过两种方式显式指定被关联的 Java 类型:
javaType属性(比如:javaType="String");@MappedTypes注解来指定与其关联的Java类型列表。如果在 javaType属性中也同时指定,则注解方式将被忽略。可以通过两种方式来指定被关联的 JDBC 类型:
jdbcType属性(比如:jdbcType="VARCHAR");@MappedJdbcTypes注解来指定与其关联的 JDBC 类型列表。 如果在javaType属性中也同时指定,则注解方式将被忽略。Mybatis注册TypeHandler就是建立一个javaType、jdbcType和TypeHandler的对应关系。根据上面所讲的情况,MyBatis注册我们写的TypeHandler时可分为下面这几种情况:
javaType和jdbcType,那么Mybatis会注册对应javaType和dbcType的TypeHandler。javaType无jdbcType,那么Mybatis会注册对应javaType和null的TypeHandler。javaType有jdbcType,若当前的TypeHandler继承了TypeReference抽象类,Mybatis会利用TypeReference的getRawType()方法取到当前TypeHandler泛型对应的javaType类型以方式1注册。javaType无jdbcType,且当前的TypeHandler未继承TypeReference抽象类,那么Mybatis会注册对应null和null的TypeHandler。
上面是讲 MyBatis 是如何注册TypeHandler,下面讲 Mybatis 是如何获取对应的TypeHandler进行类型转换的。
我们这样定义UserMapper.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.mybatis.example.mapper.UserMapper">
<resultMap id="UserResult" type="User">
<id column="id" property="id"/>
<result column="interests" property="interests" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>
</resultMap>
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyColumn="id">
insert into t_user(name, age, interests) values(#{name}, #{age}, #{interests, javaType=[Ljava.lang.String;, jdbcType=VARCHAR})
</insert>
<update id="updateUser" parameterType="User">
update t_user set name=#{name}, age=#{age}, interests=#{interests} where id=#{id}
</update>
<select id="findById" parameterType="int" resultMap="UserResult">
select * from t_user where id=#{id}
</select>
<delete id="deleteUser" parameterType="int">
delete from t_user where id=#{id}
</delete>
</mapper>
注意到UserResult中我们指定了javaType和jdbcType。获取TypeHandler的方式与注册TypeHandler中的总结完全一样。
或者我们可以通过typeHandler属性指定到底使用哪个TypeHandler,这样不指定javaType和jdbcType也可以达到同样效果。
<result column="interests" property="interests" typeHandler="org.mybatis.example.StringArrayTypeHandler"/>
mapper.xml文件的内容请参考后续文章中的动态SQL
MyBatis的配置文件mybtis-config.xml中有mappers元素,其作用是告诉MyBatis去哪里找SQL映射语句。
一般情况会有一个Maper接口和一个Mapper.xml对应(这里指xml文件的namespace与接口对应),注册Mapper的方法归纳如下:
<mappers>
<!-- 通过mapper元素的resource属性可以指定资源中的Mapper.xml文件 -->
<mapper resource="mapper/UserMapper.xml"/>
<!-- 通过mapper元素的url属性可以指定一个通过URL请求道的Mapper.xml文件 -->
<mapper url="file:///var/mappers/UserMapper.xml"/>
<!-- 通过mapper元素的class属性可以指定一个Mapper接口进行注册 -->
<mapper class="com.test.mybatis.mapper.UserMapper"/>
<!-- 通过package元素将会把指定包下面的所有Mapper接口进行注册 -->
<package name="com.test.mybatis.bean"/>
</mappers>
注意
xml文件的namespace如果与接口不对应,则相当于一个只有接口另一个只有xml文件,两者之间没有任何关联Mapper接口而无Mapper.xml,则接口中必须通过注解来实现,注册时只能通过package或者class方式注册,调用方式如下//获取注解后接口对应的对象
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用接口中的方法
User user = userMapper.findById(1);
Mapper.xml文件而无Mapper接口,则只能通过resource或url来注册,调用方式也将变成://参数中的com.mybatis.example.mapper.UserMapper是xml文件中的namespace指定的类名
//参数中的findById为指定的类中的方法
User user = sqlSession.selectOne("com.mybatis.example.mapper.UserMapper.findById", 1);
Mapper接口又Mapper.xml(namespace对应才算是都有)则接口中注解不能与xml文件重复,注册最好通过resource(通过class或package注册只会注册接口而不会关联xml文件,通过resource注册不仅会注册xml文件,还会关联对应的接口),调用方式可以采取上面两种的任意一种。标签:
原文地址:http://www.cnblogs.com/ngu113619/p/4802356.html