今天是我第一天落户博客园,想一想从mybatis框架开始写起吧。mybatis框架与Hibernate框架相比来说,专注于SQL语句,对SQL语句的要求比较高吧。
我觉得,对于mybatis框架来说,最要紧的就是两个配置文件,mybatis-config.xml和XxxxMapper.xml文件了,所以就从mybatis-config.xml开始说起吧。
首先呢是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">
可以看出这个xml文件引用了一个DTD文件的约束,所以说对框架来说是个有效的xml文件,这个两个文件都可以在官网上下载,mybatis框架也是个开源的框架,这一点是很好的
注意:!!!这个xml文件由于dtd的约束使得标签的顺序唯一,标签如果出现就必须按照严格的顺序书写(IDE是可以联网关联的,也可以自己设置)
我们来看这个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>
configuration>
configuration这个标签中就是需要给框架配置的一系列标签。
首先是properties标签:
属性配置元素properties可以将配置值写死到mybatis-config.xml中,也可以具体到一个属性文件中,并且使用属性文件的key名作为占位符,在下述的配置中,我们将数据库连接属性配置到了application.properties文件中,并且为driver,URL等属性使用了占位符。
在applications.properties文件中配置数据库连接参数,如下所示:
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
jdbc.username=xxx
jdbc.password=xxx
<properties resource="application.properties">
<property name="username" value="db_user" />
<property name="password" value="verysecurepwd" />
properties>
这样我们就可以在environment标签中调用上述配置文件中的K-V值了:
envionment标签是环境相关设置标签,使用如下:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
dataSource>
environment>
<environment id="production">
<transactionManager type="MANAGED" />
<dataSource type="JNDI">
<property name="data_source" value="java:comp/jdbc/MyBatisDemoDS" />
dataSource>
environment>
environments>
typeAliases标签:这个标签是起个别名的作用
<typeAliases>
<typeAlias alias="Student" type="pojo.Student" />
<package name="pojo" />
typeAliases>
接下来是一个比较复杂的问题:
类型处理器,这是一个在mybatis中相对复杂的问题,分为两种情况,一是内建的类型处理器,再者是自己定义的类型
MyBatis对于以下的类型使用内建的类型处理器
所有的基本数据类型、基本类型的包裹类型
byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java枚举类型等
如果是自己定义的类型,例子如下
假如在XxxxMapper.xml文件中配置一个insert插入语句,这里的phone是Student的一个内置对象,类型为PhoneNumber:
<insert id="insertStudent" parameter Type="Student">
insert into students(name,email,phone)
values(#{name},#{email},#{phone})
insert>
为了让MyBatis明白怎样处理这个自定义的Java对象类型,如PhoneNumber,我们可以创建一个自定义的类型处理器,首先我们需要处理PhoneNumber类,加入一个getAsString方法
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 str){
if(str!=null){
String[] args = str.split("-");
this.countryCode = args[0];
this.stateCode = args[1];
this.number = args[2];
}
}
public String getAsString() {
return countryCode + "-" + stateCode + "-" + number;
}
// Setters and getters
}
MyBatis提供了抽象类BaseTypeHandler
public class PhoneTypeHandler extends BaseTypeHandler{
//遇到PhoneNumber参数的时候应该如何在ps中设置值
@Override
public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)
throws SQLException {
//这个方法就是调用了PhoneNumber类中的getAsString方法
//将这个对象以一个字符串的方式存入对应的表字段中
ps.setString(i, parameter.getAsString());
}
//查询中遇到PhoneNumber类型的应该如何封装(使用列名封装)
@Override
public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
//由上面的方法可以知道
//这个方法可以将以字符串的方式存入对应的表字段中的PhoneNumber对象取出来
//调用了PhoneNumber类中的一参构造器重新封装为对象
return new PhoneNumber(rs.getString(columnName));
}
//查询中遇到PhoneNumber类型的应该如何封装(使用列的下标)
@Override
public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return new PhoneNumber(rs.getString(columnIndex));
}
//CallableStatement使用中遇到了PhoneNumber类型的应该如何封装
@Override
public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return new PhoneNumber(cs.getString(columnIndex));
}
}
最后就需要在mybatis-config.xml文件中配置一下
<typeHandlers>
<typeHandler handler="typehandlers.PhoneTypeHandler" />
<package name="typehandlers" />
typeHandlers>
接下来是mappers元素,主要用于 SQL映射
SQLMapper文件中主要是对SQL语句的映射,表明这个sql语句对应哪个方法的调用。我们需要在mybatis-config.xml文件中配置 SQLMapper文件的位置。
resource属性用来指定在classpath中的mapper文件。
url属性用来通过完全文件系统路径或者web URL地址来指向mapper文件
class属性用来指向一个mapper接口
package属性用来指向可以找到Mapper接口的包名
其实在项目中常常只要一个属性就足够定位了
<mappers>
<mapper resource="mappers/StudentMapper.xml" />
<mapper url="file:///D:/mybatisdemo/app/mappers/StudentMapper.xml" />
<mapper class="mappers.StudentMapper" />
<package name="com.mappers" />
mappers>
最后是settings元素: 全局参数设置
settings元素有好多的参数设置
注意:大多数情况下,【这些参数使用它们的默认值即可】
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25000" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="NULL" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" />
<setting name="proxyFactory" value="JAVASSIST" />
<setting name="aggressiveLazyLoading" value="true" />
<setting name="logImpl" value="LOG4J " />
<setting name="logPrefix" value="LOG4J " />
<setting name="callSettersOnNulls" value="false " />
settings>
拿其中的一个我认为最常用的,比如
这个配置是说如果当插入的值为空时给一个NULL属性,就避免了“1111”错误,比如我在将一个对象插入到表中的时候,一个属性没有值,在有些环境中数据库无法解析这个空的指向,就会报出“1111”错误,如果设置了这个属性这个空的指向就可以设为空
在package org.apache.ibatis.type包中中有一个枚举JdbcType,定义了一系列类型,但是一个数据库不可能完全支持这些类型,源码如下:
package org.apache.ibatis.type; import java.sql.Types; import java.util.HashMap; import java.util.Map; /** * @author Clinton Begin */ public enum JdbcType { /* * This is added to enable basic support for the * ARRAY data type - but a custom type handler is still required */ ARRAY(Types.ARRAY), BIT(Types.BIT), TINYINT(Types.TINYINT), SMALLINT(Types.SMALLINT), INTEGER(Types.INTEGER), BIGINT(Types.BIGINT), FLOAT(Types.FLOAT), REAL(Types.REAL), DOUBLE(Types.DOUBLE), NUMERIC(Types.NUMERIC), DECIMAL(Types.DECIMAL), CHAR(Types.CHAR), VARCHAR(Types.VARCHAR), LONGVARCHAR(Types.LONGVARCHAR), DATE(Types.DATE), TIME(Types.TIME), TIMESTAMP(Types.TIMESTAMP), BINARY(Types.BINARY), VARBINARY(Types.VARBINARY), LONGVARBINARY(Types.LONGVARBINARY), NULL(Types.NULL), OTHER(Types.OTHER), BLOB(Types.BLOB), CLOB(Types.CLOB), BOOLEAN(Types.BOOLEAN), CURSOR(-10), // Oracle UNDEFINED(Integer.MIN_VALUE + 1000), NVARCHAR(Types.NVARCHAR), // JDK6 NCHAR(Types.NCHAR), // JDK6 NCLOB(Types.NCLOB), // JDK6 STRUCT(Types.STRUCT), JAVA_OBJECT(Types.JAVA_OBJECT), DISTINCT(Types.DISTINCT), REF(Types.REF), DATALINK(Types.DATALINK), ROWID(Types.ROWID), // JDK6 LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6 SQLXML(Types.SQLXML), // JDK6 DATETIMEOFFSET(-155); // SQL Server 2008 public final int TYPE_CODE; private static MapcodeLookup = new HashMap (); static { for (JdbcType type : JdbcType.values()) { codeLookup.put(type.TYPE_CODE, type); } } JdbcType(int code) { this.TYPE_CODE = code; } public static JdbcType forCode(int code) { return codeLookup.get(code); } }
常用的标签就这些了,这些标签的顺序为
properties,settings,typeAliases,typeHandlers,environments,mappers
有任何不足的地方欢迎大家指出,我会学习并且修改