mybatis框架简介

mybatis框架与Hibernate框架相比来说,专注于SQL语句,对SQL语句的编写能力要求较高,同时对数据库的事务也需要有好的理解,最主要的功能是mybatis框架可以将查询到的结果集自动封装成对象。

首先要进行一个环境的搭建:

  在这里我使用的IDE是eclipse

  使用的mybatis的版本是3.4.6的,同时也将源码的jar包下载下来,还有必备的两个DTD约束文件mybatis-3-mapper.dtd和mybatis-3-config.dtd

  使用的数据库是MySQL

  由于mybatis也是相当于对JDBC的封装,所以需要JDBC的jar包

  我也加入了一个log4j的日志支持

  

我们需要先将项目搭建起来

  

数据库建表:

create table tbl_customer(
id int primary key auto_increment,
name varchar(20) ,
password varchar(200),
zip varchar(20),
address varchar(200),
telephone varchar(15),
email varchar(50)
);
create table tbl_book(
id int primary key auto_increment,
name varchar(100),
price double
); create table tbl_order(
id int primary key auto_increment,
cost double,
orderDate date,
customer_id int references tbl_customer(id)
); create table tbl_orderline(
id int primary key auto_increment,
num int,
order_id int references tbl_order(id),
book_id int references tbl_book(id)
);
insert into tbl_book values(1,'JAVA核心技术',81);
insert into tbl_book values(2,'UNIX技术手册',21);
insert into tbl_book values(3,'ORACLE9I参考手册',108);
insert into tbl_book values(4,'JSP设计(第三版)',59);
insert into tbl_book values(5,'JAVA SERVLET 编程(第二版)',38);
insert into tbl_book values(6,'XML 高级编程(第2版)',97);
insert into tbl_book values(7,'精通STRUTS:基于MVC的JAVA WEB设计与开发',36);
insert into tbl_book values(8,'精通HIBERNATE:JAVA对象持久化技术详解',44);
insert into tbl_book values(9,'SPRING IN ACTION中文版',29);
insert into tbl_book values(10,'精通EJB 3.0',44);

逆向数据库到模型:

我觉得,对于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标签是环境相关设置标签,使用如下:

<!-- 这里的环境可以有多个,环境id不同,作用不同,如下,第一个environment作用是开发,第一个environment作用是生产 -->
<environments default="development">
<!-- 这里的id是指环境的id,常常写为自己的作用 -->
<environment id="development">
<!-- 这个属性是连接管理类型 一般有2个值可选-->
<!-- JDBC 是需要应用程序自己管理事务 -->
<!-- 例如,部署到ApacheTomcat的应用程序,需要应用程序自己管理事务。因为ApacheTomcat不会帮我们管理事务。 -->
<!-- MANAGED 是让服务器自动管理事务 像glassfish 服务器-->
<transactionManager type="JDBC" />
<!-- dataSource的类型type属性可以配置成其内置类型之一,如UNPOOLED,POOLED,JNDI。 -->
<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标签:这个标签是起个别名的作用

<!-- 这个属性就是对pojo类起个别名 -->
<typeAliases>
<!-- 这里的意思是将 pojo.Student 类别名为 Student-->
<typeAlias alias="Student" type="pojo.Student" />
<!-- 这里的意思是将 pojo包下的所有类进行别名,比如pojo.Student 就会别名为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<T> ,我们可以继承此类创建自定义类型处理器。

public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{

        //遇到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" />
<!-- 允许JDBC支持生成的键。需要适合的驱动。 -->
<setting name="useGeneratedKeys" value="false" />
<!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单、没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) -->
<setting name="autoMappingBehavior" value="PARTIAL" />
<!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 -->
<setting name="defaultStatementTimeout" value="25000" />
<!-- 允许在嵌套语句中使用分页(RowBounds)默认false -->
<setting name="safeRowBoundsEnabled" value="false" />
<!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。默认false -->
<setting name="mapUnderscoreToCamelCase" value="false" />
<!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 -->
<setting name="localCacheScope" value="SESSION" />
<!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 -->
<setting name="jdbcTypeForNull" value="NULL" />
<!-- 指定对象的哪个方法触发一次延迟加载。 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" />
<!-- CGLIB | JAVASSIST 默认JAVASSIST(MyBatis 3.3 or above) -->
<!-- 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 -->
<setting name="proxyFactory" value="JAVASSIST" />
<!-- 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 -->
<setting name="aggressiveLazyLoading" value="true" />
<!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 -->
<setting name="logImpl" value="LOG4J " />
<!-- 指定 MyBatis 增加到日志名称的前缀。值可以是任意字符串 -->
<setting name="logPrefix" value="LOG4J " />
<!-- 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 默认false-->
<setting name="callSettersOnNulls" value="false " />
</settings>

拿其中的一个我认为最常用的,比如 <setting name="jdbcTypeForNull" value="NULL" /> 这个设置就可以有效的帮助我们避免“1111”错误

这个配置是说如果当插入的值为空时给一个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 Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>(); 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

关于mybatis-config.xml文件的基础解释的更多相关文章

  1. MyBatis(2):config.xml文件

    前言 前一篇文章,讲了MyBatis入门,讲到了MyBatis有两个基本的配置文件,一个用来配置环境信息,一个用来写SQL语句.前者我把它命名为config.xml,config.xml的内容是: 1 ...

  2. MyBatis2:config.xml文件

    前言 前一篇文章,讲了MyBatis入门,讲到了MyBatis有两个基本的配置文件,一个用来配置环境信息,一个用来写SQL语句.前者我把它命名为config.xml,config.xml的内容是: & ...

  3. MyBatis Mapper.xml文件中 $和#的区别

    MyBatis Mapper.xml文件中 $和#的区别   网上有很多,总之,简略的写一下,作为备忘.例子中假设参数名为 paramName,类型为 VARCHAR . 1.优先使用#{paramN ...

  4. Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理

    Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理 >>>>>>>>>>>>>>>>& ...

  5. Android项目中的config.xml文件 “config.xml”

    Android应用程序需要保存一些配置时,可以将这些配置项放置到values/config.xml文件中. 实例分析: <?xml version="1.0" encodin ...

  6. mybatis mapper xml文件的导入方式和查询方式

    mybatis mapper xml文件的导入方式和查询方式 ssm框架 Mybatis  mapper与SQLSession的关系 每个基于MyBatis的应用都是以一个SqlSessionFact ...

  7. mybatis mapper xml文件配置resultmap时,id行和result行有什么区别?

    mybatis mapper xml文件配置resultmap时,id行和result行有什么区别? <resultMap id = "CashInvoiceMap" typ ...

  8. mybatis的xml文件中的CDATA的使用

    mybatis的xml文件中的CDATA的使用 <!--查询列表--> <select id="queryListPage" parameterType=&quo ...

  9. mybatis Mapper XML 文件

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

随机推荐

  1. import threading线程进程

    cpu在执行一个子线程的时候遇到sleep就会利用这段停顿时间去执行另一个子线程.两个子线程谁先跳出sleep就执行谁. import threadingimport time start = tim ...

  2. java-day08

    继承概念 继承是多态的前提,主要用于解决共性抽取 特点 子类可以拥有父类的内容,子类也可以有自己的专属内容 格式 public class 父类{} public class 子类 extends 父 ...

  3. CVE-2015-0235

    看了下代码,由于各人能力问题,只是了解了漏洞的起因,知道哪里出了问题,但是不知道怎么用阿... 可怜... 这种漏洞,公布出来,只要不给EXP,估计威胁都不大.或者,就是我脑筋太死??? 首先,是网上 ...

  4. JS流程控制语句 多种选择(Switch语句) 当有很多种选项的时候,switch比if else使用更方便。

    多种选择(Switch语句) 当有很多种选项的时候,switch比if else使用更方便. 语法: switch(表达式) { case值1: 执行代码块 1 break; case值2: 执行代码 ...

  5. 判断JS对象是否为空的几种方式

    .将json对象转化为json字符串,再判断该字符串是否为"{}" var data = {}; var b = (JSON.stringify(data) == "{} ...

  6. 关于安装了sqlite对于vs的组件,重启vs后,在外面可以连接sqlite数据库,但是在建立实体模型时没有sqlite数据源的问题

    出自:http://bbs.csdn.net/topics/390917337 兄弟,刚刚在stackoverflow上找到了解决方法了http://stackoverflow.com/questio ...

  7. Python操作MySQL以及数据库索引

    目录 python操作MySQL 安装 使用 SQL注入问题 MySQL的索引 为什么使用索引 索引的种类 主键索引 唯一索引 普通索引 索引优缺点 不会命中索引的情况 explain 索引覆盖 My ...

  8. Python更新后ros用不了的bug

    一.原因 我同时安装了python2.7 和3.5,而且将python默认配置为python3.5,所以ros并不支持,所以提示找不到. 2.解决方式 通过修改不同版本的python的优先级,将pyt ...

  9. 一个windows 两个jar

    设置两个子JAVA_HOME,一个总设置两个子JAVA_HOME:JAVA_HOME6 = C:\Program Files\Java\jdk1.6.0_43JAVA_HOME8 = C:\Progr ...

  10. Nginx是什么

    Nginx很强大,通常作为反向代理服务器,什么是反向代理服务器?就是客户端发送请求给Nginx ,Nginx收到请求后将请求转发给真正的服务器,然后接受服务器处理的结果,最后发送给客户端.客户端以为N ...