mybatis环境搭建。这里用的是eclipse、mysql驱动包是5.1.36版本,mybatis版本是3.3.0,利用maven搭建项目。
首先,探讨一下为什么要用mybatis。大家都知道mybatis是orm(对象关系映射)的一种解决方案。数据持久化层是整个系统性能的关键。那我们为什么用mybatis呢,用了有什么好处呢?原因如下:
1、MyBatis支持数据库连接池,消除了为每一个请求创建一个数据库连接的开销。
2、MyBatis提供了内建的缓存机制,在SqlSession级别提供了对SQL查询结果的缓存。即:如果你调用了相同的select查询,MyBatis会将放在缓存的结果返回,而不会去再查询数据库。(疑问:如果有数据更新,这查询就不准了,什么时候释放这块缓存)
3、MyBatis框架并没有大量使用代理机制,因此对于其他过度使用代理的ORM框架而言,MyBatis可以获得更好的性能。(由于动态代理本身有很大的内存消耗,大量使用动态代理,会使整个系统性能变得很差)
当然,在软件开发过程中,并没有通用的解决方案。如果你的应用是面向对象模型,并且向动态生成SQL语句,那么MyBatis可能就不符合要求。另外如果你想让你的应用有一个传递性的缓存机制的话(保存父对象时也应该保存关联的子对象),Hibernate更适合。
一、创建项目
执行maven命令,创建WEB项目。
mvn archetype:generate -DgroupId=orm.mybatis -DartifactId=orm_mybatis_test -DarchetypeArtifactId=maven-archetype-webapp -DinteractivMode=false
二、pom.xml文件中加入mysql驱动包和mybatis
<properties>
<mysql.version>5.1.36</mysql.version>
<mybatis.version>3.3.0</mybatis.version>
<junit.version>3.8.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 数据库驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- orm-mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
三、添加mybatis配置文件mybatis-config.xml
在这里配置mybatis最主要的配置文件mybatis-config.xml,里面可以配置settings(全局参数设置)、typeAlias(别名)、typeHandlers、environment、transactionManager(事务)、dataSource(包含了JDBC连接参数)和配置映射器Mapper XML文件,映射文件包含了SQL语句的映射;配置是否开启缓存等等。mybatis有内建的SqlSession级别的缓存机制,用于缓存Select语句查询出来的结果。除此之外,mybatis提供了与多种第三方缓存类库的集成支持,如EHCache,OSCache。
然后我们使用mybatis-config.xml内的信息创建SqlSessionFactory对象。每个数据库环境应该就一个SqlSessionFactory对象实例。mybatis最关键的组成部分就是SqlSessionFactory,我们可以从中获取SqlSession,并执行映射的SQL语句。SqlSessionFactory对象可以通过基于XML的配置信息或者Java API创建。
<?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>
<!-- 引用db.properties配置文件 -->
<properties resource="db.properties" />
<!-- 命名空间 -->
<typeAliases>
<typeAlias alias="Account" type="orm.mybatis.model.Account" />
</typeAliases>
<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>
<!-- 配置映射文件 -->
<mappers>
<mapper resource="orm/mybatis/model/AccountMapper.xml" />
</mappers>
</configuration>
下面我们逐个讨论上述配置文件的组成部分,先从最重要的部分开始:
1、environments(环境变量)
MyBatis支持配置多个dataSource环境,可以将应用部署到不同的环境上,如DEV,TEST,UAT(用户验收环境),PRODUCTION(生产环境),可以通过默认environment值设置成想要的environment id值。在上述的配置中,默认的环境environment被设置成development。当需要将程序部署到生产服务器上时,你不需要修改什么配置,只需要将默认环境environment值设置成生产环境的environment id属性即可。
2、dataSource(数据源)
dataSource元素被用来配置数据库连接属性。dataSource的类型可以配置其内置类型之一,如UNPOOLED,POOLED,JNDI。
1)、如果将类型设置成UNPOOLED,MyBatis会为每一个数据库操作创建一个新的连接,并关闭它。该方式只适用于只有小规模数量并发用户的简单应用程序上。
2)、如果将类型设置成POOLED,MyBatis会创建一个数据库连接池,连接池中的一个连接将会被用作数据库操作。一旦数据库操作完成,MyBatis会将此连接返回给连接池。在开发和测试环境中,经常使用此方式。
3)、如果将类型设置JNDI,MyBatis从在应用服务器向配置好的JNDI数据源dataSource获取数据库连接。在生产环境中,优先考虑这种方式。
3、transactionManager(事务管理器)
MyBatis支持两种类型的事物管理器:JDBC and MANAGED
四、创建数据库和表
CREATE DATABASE IF NOT EXISTS `ym_test`
DEFAULT CHARACTER SET = `UTF8`;
-- Create a table named 'account'
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`money` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- Insert a test record
insert into account(name, money) values('A', 1000);
五、创建Account类和对应的映射文件
package orm.mybatis.model;
import java.io.Serializable;
public class Account implements Serializable {
private static final long serialVersionUID = 1276869542913292500L;
private int id;
private String name;
private float money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getMoney() {
return money;
}
public void setMoney(float money) {
this.money = money;
}
}
映射文件AccountMapper.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="orm.mybatis.model.AccountMapper">
<!-- 可以使用cache-ref元素来引用第三方缓存 -->
<!-- <cache-ref></cache-ref> -->
<!-- 配置cache -->
<!-- <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> -->
<!-- 配置结果映射(数据记录与pojo的映射) -->
<resultMap type="Account" id="BaseResultMap">
<result column="id" property="id" />
<result column="name" property="name" />
<result column="money" property="money" />
</resultMap>
<!-- 配置sql(定义可重用的SQL代码段) -->
<sql id="Base_Column_List">
id, name, money
</sql>
<sql id="Example_Where_Clause">
where 1=1
<trim suffixOverrides=",">
<if test="id != null">
and id = #{id}
</if>
<if test="name != null">
and name = #{name}
</if>
<if test="money != null">
and money = #{money}
</if>
</trim>
</sql>
<!-- 配置insert -->
<insert id="insertAccount" parameterType="Object">
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into account(id, name, money)
values(#{id}, #{name}, #{money})
</insert>
<!-- 配置update -->
<update id="updateAccount" parameterType="java.lang.String">
update account set
money=money+100
where name=#{name}
</update>
<!-- 分页查询捐赠记录 -->
<select id="queryByList" resultMap="BaseResultMap" parameterType="Object">
select
<include refid="Base_Column_List" />
from account
<include refid="Example_Where_Clause" />
<if test="pager.orderCondition != null and pager.orderCondition != ''">
${pager.orderCondition}
</if>
<if test="pager.mysqlQueryCondition != null and pager.mysqlQueryCondition != ''">
${pager.mysqlQueryCondition}
</if>
</select>
<select id="queryById" resultMap="BaseResultMap" parameterType="java.lang.String">
select
<include refid="Base_Column_List" />
from account where name=#{name}
</select>
<!-- 列表总数 -->
<select id="queryByCount" resultType="java.lang.Integer" parameterType="Object">
select count(1) from account
<include refid="Example_Where_Clause" />
</select>
</mapper>
创建Mapper类:
package orm.mybatis.model;
public interface AccountMapper {
void insertAccount(Account account);
int queryByCount(Account account);
Account queryById(String name);
}
注意映射文件中的namespace的值被设置成Mapper接口的完全限定名,这使我们可以使用接口来调用映射的SQL语句。
六、编写测试类
package orm.mybatis.main;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;
import orm.mybatis.model.Account;
import orm.mybatis.model.AccountMapper;
public class TestMyBatis {
private static final Logger log = Logger.getLogger(TestMyBatis.class);
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
/**
* before和beforeclass区别
* @befor 在每个测试方法之前都会运行一次,只需声明成public
* @beforeclass 在类中只运行一次,必须声明成public static
*/
@BeforeClass
public static void initial() {
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
log.error("Error thrown while reading the configuration: {}", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error("Error thrown while closing the reader: {}", e);
}
}
}
}
@Test
public void queryTest() {
SqlSession session = sqlSessionFactory.openSession();
AccountMapper accountMapper = session.getMapper(AccountMapper.class);
// int count = accountMapper.queryByCount(null);
// System.out.println("count=" + count);
Account account = accountMapper.queryById("B");
System.out.println("id=" + account.getId());
System.out.println("name=" + account.getName());
System.out.println("money=" + account.getMoney());
// accountMapper.insertAccount(account);
}
}