一、 使用Maven创建一个Web项目
使用Maven创建web项目在此不做赘述了。
二、使用MyBatis完成MySQL数据库访问
2.1、添加依赖
要完成使用MyBatis访问MySQL数据库,需要添加一些依赖包,包含MyBatis3,连接驱动,JUnit,Log4j2等。可以去共享资源库中搜索,第一个网站地址是:http://mvnrepository.com/, 这里以搜索连接驱动为示例,搜索后的结果有5.xx版许多,也有6.xx版,但不建议使用6.xx版,因为MyBatis3不支持。
配置pom.xml文件:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<mybatis.version>3.2.8</mybatis.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
2.2、准备数据
打开MySQL数据库,创建一个表,这里以user表为例。
SQL脚本如下:
/*
Navicat MySQL Data Transfer
Source Server : localhost_mysql
Source Server Version : 50517
Source Host : localhost:3306
Source Database : mybatis
Target Server Type : MYSQL
Target Server Version : 50517
File Encoding : 65001
Date: 2018-12-05 09:18:17
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '张三', '2018-12-19', '2', '河北邯郸');
INSERT INTO `user` VALUES ('2', '李四', '2018-12-11', '1', '黑龙江哈尔滨');
INSERT INTO `user` VALUES ('3', '王五', '2018-12-03', '1', '吉林长春');
INSERT INTO `user` VALUES ('4', '赵六', '2018-12-04', '2', '辽宁大连');
2.3、创建Java Bean
package cn.liuw.po;
import java.util.Date;
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
2.4、创建实例与表的映射文件
这里用接口+XML的形式完成,User数据访问接口如下:
package cn.liuw.dao;
import cn.liuw.po.User;
import java.util.List;
public interface IUserDao {
/**
* 获得所有图书
*/
public List<User> getAllUser();
}
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>
<select id="getAllUser" resultType="cn.liuw.po.User">
SELECT * FROM user
</select>
</mapper>
2.5、创建mybatis-cfg.xml文件
mybatis-cfg.xml文件用于配置MyBatis的运行环境,内容如下:
<?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="db.properties"></properties>
<!-- 类型别名 -->
<typeAliases>
<package name="cn.liuw.po" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}" />
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 引入映射文件 -->
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
因为配置中依赖了db.properties文件,该文件用于指定数据库的连接信息,内容如下:
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root
配置日志文件:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2.6、实现数据访问功能
为了更加方便的复用MyBatis实现数据访问不需要频繁的创建SQLSessionFactory和SQLSession对象,封装一个MyBatisUtil工具类如下:
package cn.liuw.util;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
/**
* @ClassName MyBatisUtil
* @Description TODO
**/
public class MyBatisUtil {
private static SqlSessionFactory factory = null;
public static SqlSessionFactory getSqlSessionFactory(){
if(factory == null){
//获得环境配置文件流
InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("mybatis-cfg.xml");
//创建sql会话工厂
factory = new SqlSessionFactoryBuilder().build(config);
}
return factory;
}
//获得会话
public static SqlSession getSession(){
return getSqlSessionFactory().openSession(true);
}
//获得sql会话
public static SqlSession getSession(boolean isAutoCommit){
return getSqlSessionFactory().openSession(isAutoCommit);
}
}
创建类UserDaoImpl实现接口UserDao,这里要通过MyBatis实现数据访问功能,内容如下:
package cn.liuw.dao.impl;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
import cn.liuw.service.IUserService;
import cn.liuw.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @ClassName 实现User数据访问
**/
public class UserDaoImpl implements IUserDao{
@Override
public List<User> getAllUser() {
//获得会话对象
SqlSession session = MyBatisUtil.getSession();
try {
//通过MyBatis实现接口UserDao,返回实例
IUserDao userDao = session.getMapper(IUserDao.class);
return userDao.getAllUser();
}finally {
session.close();
}
}
}
测试用例TestBookTypeDAOImpl.java文件如下:
import cn.liuw.dao.IUserDao;
import cn.liuw.dao.impl.UserDaoImpl;
import cn.liuw.po.User;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class TestUserDaoImpl {
public static IUserDao userDao;
@BeforeClass
public static void beforeClass(){
userDao = new UserDaoImpl();
}
@Test
public void testGetAllUser(){
List<User> users = userDao.getAllUser();
for(User user:users) {
System.out.println(user);
}
assertNotNull(users);
}
}
运行结果:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 720461041.
DEBUG [main] - ==> Preparing: SELECT * FROM user
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 4
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2af15cf1]
DEBUG [main] - Returned connection 720461041 to pool.
User{id=1, username='张三', sex='2', birthday=Wed Dec 19 00:00:00 CST 2018, address='河北邯郸'}
User{id=2, username='李四', sex='1', birthday=Tue Dec 11 00:00:00 CST 2018, address='黑龙江哈尔滨'}
User{id=3, username='王五', sex='1', birthday=Mon Dec 03 00:00:00 CST 2018, address='吉林长春'}
User{id=4, username='赵六', sex='2', birthday=Tue Dec 04 00:00:00 CST 2018, address='辽宁大连'}
三、使用Spring4.X整合MyBatis3.X初级版
在MyBatis的github官网(https://github.com/mybatis/spring)中有一个叫MyBatis Spring Adapter(MyBatis-Spring)的库,暂且翻译成:MyBatis Spring适配器,它的作用是:原话:“MyBatis-Spring adapter is an easy-to-use Spring3 bridge for MyBatis sql mapping framework.”,就是了为更容易的将MyBatis与Spring整合,充分发挥二两结合的优势,它相当于一个桥。
什么是:MyBatis-Spring?
MyBatis-Spring会帮助你将MyBatis代码无缝地整合到Spring中。使用这个类库中的类,Spring将会加载必要的MyBatis工厂类和session类。这个类库也提供一个简单的方式来注入MyBatis数据映射器和SqlSession到业务层的bean中。而且它也会处理事务,翻译MyBatis的异常到Spring的DataAccessException异常(数据访问异常,译者注)中。最终,它并不会依赖于MyBatis,Spring或MyBatis-Spring来构建应用程序代码。
3.1、修改pom.xml添加依赖
为了将Spring与MyBatis整合完成,需要依赖MyBatis,因为在上面的示例中已依赖完成,这里就不再需要,主要需依赖的是Spring核心,AOP,JDBC,MyBatis-Spring等jar包。具体的依赖结果pom.xml文件如下所示:
<name>Learning-Spring Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>4.3.1.RELEASE</spring.version>
<mybatis.version>3.2.8</mybatis.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!-- 其他 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.3</version>
</dependency>
</dependencies>
3.2、创建Spring上下文初始化配置文件
该文件取名为ApplicationContext.xml主要原因是“约束优于配置”的理由,使用Web监听器加载Spring时会默认找该名称的文件。在文件中我们可像以前学习Spring一样配置IOC与AOP,只不过这里整合了一些MyBatis内容。文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 0.db.properties -->
<context:property-placeholder location="db.properties" ignore-unresolvable="true" />
<!-- 1.定义JDBC数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}" />
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 2.创建一个SqlSession -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-cfg.xml" />
</bean>
<!-- 3.创建一个UserDao -->
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 指定映射文件 -->
<property name="mapperInterface" value="cn.liuw.dao.IUserDao" />
<!-- 指定sql会话工厂 -->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>
从上面的代码可以看到分别创建了一个驱动管理数据源的对象,会话工厂与实现数据访问的对象通过Spring IOC完成,而不再是硬编码。第1段配置与下面的代码功能基本类似:
private static SqlSessionFactory factory=null;
public static SqlSessionFactory getSqlSessionFactory(){
if(factory==null){
// 获得环境配置文件流
InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("mybatis-cfg.xml");
// 创建sql会话工厂
factory = new SqlSessionFactoryBuilder().build(config);
}
return factory;
}
第2段配置与下面的java代码基本类似:
SqlSession session = MyBatisUtil.getSession();
try {
IUserDao userDao = session.getMapper(IUserDao.class);
return userDao.getAllUser();
} finally {
session.close();
}
配置mybatis-cfg.xml文件:
因为在applicationContext.xml中配置了数据源,所以mybatis-cfg.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>
<mappers>
<!-- 引入映射文件 -->
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
3.3、测试运行
import cn.liuw.boot.ApplicationCfg;
import cn.liuw.dao.IUserDao;
import cn.liuw.po.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class Test06 {
@Test
public void demo01(){
//初始化容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获得bean
IUserDao userDao = context.getBean("userDao",IUserDao.class);
//访问数据库
List<User> users = userDao.getAllUser();
for (User user:users) {
System.out.println(user);
}
assertNotNull(users);
}
}
运行结果:
DEBUG [main] - Parsed configuration file: 'class path resource [mybatis-cfg.xml]'
DEBUG [main] - Property 'mapperLocations' was not specified or no matching resources found
DEBUG [main] - Finished creating instance of bean 'sqlSessionFactory'
DEBUG [main] - Creating shared instance of singleton bean 'userDao'
DEBUG [main] - Creating instance of bean 'userDao'
DEBUG [main] - Eagerly caching bean 'userDao' to allow for resolving potential circular references
DEBUG [main] - Returning cached instance of singleton bean 'sqlSessionFactory'
DEBUG [main] - Invoking afterPropertiesSet() on bean with name 'userDao'
DEBUG [main] - Finished creating instance of bean 'userDao'
DEBUG [main] - Unable to locate LifecycleProcessor with name 'lifecycleProcessor':
using default [org.springframework.context.support.DefaultLifecycleProcessor@65a8d7fd]
DEBUG [main] - Returning cached instance of singleton bean 'lifecycleProcessor'
DEBUG [main] - Returning cached instance of singleton bean 'sqlSessionFactory'
DEBUG [main] - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
DEBUG [main] - Returning cached instance of singleton bean 'userDao'
DEBUG [main] - Creating a new SqlSession
DEBUG [main] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f76eb40]
was not registered for synchronization because synchronization is not active
DEBUG [main] - Fetching JDBC Connection from DataSource
DEBUG [main] - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/mybatis]
DEBUG [main] - JDBC Connection [com.mysql.jdbc.JDBC4Connection@79dce7a9] will not be managed by Spring
DEBUG [main] - ==> Preparing: SELECT * FROM user
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 4
DEBUG [main] - Closing non transactional SqlSession
DEBUG [main] - Returning JDBC Connection to DataSource
User{id=1, username='张三', sex='2', birthday=Wed Dec 19 00:00:00 CST 2018, address='河北邯郸'}
User{id=2, username='李四', sex='1', birthday=Tue Dec 11 00:00:00 CST 2018, address='黑龙江哈尔滨'}
User{id=3, username='王五', sex='1', birthday=Mon Dec 03 00:00:00 CST 2018, address='吉林长春'}
User{id=4, username='赵六', sex='2', birthday=Tue Dec 04 00:00:00 CST 2018, address='辽宁大连'}
Process finished with exit code 0
小结:此处的整合还是相对基础,更完善的整合内容将在后面的章节实现。另外在MyBatisCfg.xml文件中可以删除运行环境中数据源配置部分的内容,如下图所示。我们当前的示例使用的是Spring提供的数据源,其实也可以使用一第三方的数据源管理,如C3P0,Druid(德鲁伊,阿里巴巴开发)等。
四、Spring集成MyBatis升级版
4.1、映射接口类自动扫描配置
在示例3的applicationContext.xml配置文件中有一段实现IUserDao接口实例的创建工厂,配置如下:
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 指定映射文件 -->
<property name="mapperInterface" value="cn.liuw.dao.IUserDao" />
<!-- 指定sql会话工厂 -->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
如果有多个表,则需要配置多段信息,麻烦。我们可以通过自动扫描一次完成,配置如下:
<!--自动扫描映射接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定sql会话工厂,在上面配置过的 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!-- 指定基础包,即自动扫描cn.liuw.dao这个包以及它的子包下的所有映射接口类 -->
<property name="basePackage" value="cn.liuw.dao"></property>
</bean>
需要注意的是这里的sql会话工厂的指定可以使用sqlSessionFactoryBeanName属性指定,也可以使用sqlSessionFactory属性指定,但建议大家使用sqlSessionFactoryBeanName,否则会因为加载的先后顺序问题引起读不到properties文件的内容。
4.2、最终applicationContext.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--属性占位文件引入,可以通过${属性名}获得属性文件中的内容-->
<context:property-placeholder location="classpath:db.properties"/>
<!--定义一个jdbc数据源,创建一个驱动管理数据源的bean -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--创建一个sql会话工厂bean,指定数据源 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- mybatis配置-->
<property name="configLocation" value="classpath:mybatis-cfg.xml"/>
<!--指定sql映射xml文件的路径 -->
<property name="mapperLocations"
value="classpath:mapper/*Mapper.xml"></property>
</bean>
<!--自动扫描映射接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定sql会话工厂,在上面配置过的 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!-- 指定基础包,即自动扫描cn.liuw.dao这个包以及它的子包下的所有映射接口类 -->
<property name="basePackage" value="cn.liuw.dao"></property>
</bean>
<!--下面的配置暂时未使用 -->
<context:component-scan base-package="cn.liuw" />
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
配置mybatis-cfg.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>
<!-- 类型别名 -->
<typeAliases>
<package name="cn.liuw.dao" />
</typeAliases>
</configuration>
创建UserDao接口:
package cn.liuw.dao;
import cn.liuw.po.User;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Description 用户数据访问接口
**/
@Repository
public interface UserDao {
/**
* 获得所有图书
*/
public List<User> getAllUser();
}
创建mapper下的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="cn.liuw.dao.UserDao">
<select id="getAllUser" resultType="cn.liuw.po.User">
SELECT * FROM user
</select>
</mapper>
测试:
public class Test06 {
@Test
public void demo01(){
//初始化容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获得bean
UserDao userDao = context.getBean(UserDao.class);
//访问数据库
List<User> users = userDao.getAllUser();
for (User user:users) {
System.out.println(user);
}
assertNotNull(users);
}
}
运行结果:
User{id=1, username='张三', sex='2', birthday=Wed Dec 19 00:00:00 CST 2018, address='河北邯郸'}
User{id=2, username='李四', sex='1', birthday=Tue Dec 11 00:00:00 CST 2018, address='黑龙江哈尔滨'}
User{id=3, username='王五', sex='1', birthday=Mon Dec 03 00:00:00 CST 2018, address='吉林长春'}
User{id=4, username='赵六', sex='2', birthday=Tue Dec 04 00:00:00 CST 2018, address='辽宁大连'}
Process finished with exit code 0
注意:
- 如果接口名和xml文件名一致且在一个包下,这里就不需要指定mapperLocations了。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-cfg.xml"/>
<!-- 不需要指定了,mybatis默认从指定包找对应接口的xml文件 -->
<!--<property name="mapperLocations"
value="classpath:mapper/*Mapper.xml"></property>-->
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<property name="basePackage" value="cn.liuw.dao"></property>
</bean>
- applicationContext.xml中指定Mapper.xml位置,可以修改为:在mybatis-cfg.xml中指定<mappers></mappers>。
4.3、数据源与连接池
通过连接池可以增加数据访问的性能,因为访问数据库时建立连接与释放连接是耗时操作,JDBC默认不带连接池技术,但MyBatis是内置连接池功能的,还有一些第三方知名的连接池技术如:DBCP、C3P0、Druid(德鲁伊)。
4.3.1、DBCP
DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个 jar 文件:Commons-dbcp.jar:连接池的实现、Commons-pool.jar:连接池实现的依赖库,常用属性如下:
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
与Spring配置整合:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="maxActive" value="100"></property>
<property name="maxIdle" value="30"></property>
<property name="maxWait" value="500"></property>
<property name="defaultAutoCommit" value="true"></property>
</bean>
使用上面的代码替换原数据源的创建。
4.3.2、C3P0
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。dbcp没有自动回收空闲连接的功能,而c3p0有自动回收空闲连接功能。
在pom.xml中添加依赖:
<!--c3p0 连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
在与Spring整合时修改applicationContext.xml,设置如下:
<!--定义一个jdbc数据源,创建一个驱动管理数据源的bean -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="acquireIncrement" value="5"></property>
<property name="initialPoolSize" value="10"></property>
<property name="minPoolSize" value="5"></property>
<property name="maxPoolSize" value="20"></property>
</bean>
4.3.3、Druid(德鲁伊)
Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。阿里巴巴是一个重度使用关系数据库的公司,我们在生产环境中大量的使用Druid,通过长期在极高负载的生产环境中实际使用、修改和完善,让Druid逐步发展成最好的数据库连接池。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。
在与Spring整合时设置:
<!-- 配置数据源,使用的是alibaba的Druid(德鲁伊)数据源 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" />
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="20" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<!--
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="33" />
-->
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<!-- <property name="filters" value="stat" /> -->
<property name="filters" value="mergeStat" />
</bean>
使用上面的代码替换原数据源的创建。
maven依赖方式:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
github:https://github.com/alibaba/druid,阿里的其它开源框架:https://github.com/alibaba。
五、在Web项目中启动Spring容器
在Web项目中当Web容器启动时我们要同时启动Spring容器,有三种办法,第一种使用监听器启动,第二使用Servlet启动,第三使用MVC框架的扩展点启动,这里主要选择第一种,因为监听器的启动时机早于Servlet。
使用监听器启动Spring容器
我们需要使用到Spring定义好的一个监听器:org.springframework.web.context.ContextLoaderListener,该监听器在包Spring-web.x.x.x.jar下,修改pom.xml文件,添加依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
修改web.xml文件,新增监听器声明,代码如下:
<listener>
<description>Spring容器启动监听器</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
当监听器在启动Spring容器时会自动查找Web-INF/lib目录下名为applicationContext.xml配置文件,当然也可以设置参数指定配置文件的具体位置,特别是有多个配置文件的情况,指定办法如下:
<listener>
<description>Spring容器加载监听器</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
如果有多个配置文件则可以通过逗号分开。怎么判断是否启动成功,则可以参考本文第二点,获得ApplicationContext实例,也可以查看tomcat启动时的信息,如果没有出现错误且能找到如下说明基本成功。
运行结果:
六、基于注解的声明式事务管理配置
MyBatis-Spring利用了存在于Spring中的DataSourceTransactionManager管理事务。
一旦Spring的PlatformTransactionManager配置好了,你可以在Spring中以你通常的做法来配置事务。@Transactional注解和AOP方式的配置都是支持的。在事务处理期间,一个单独的SqlSession对象将会被创建和使用。当事务完成时,这个session会以合适的方式提交或回滚。一旦事务创建之后,MyBatis-Spring将会透明的管理事务。在你的DAO类中就不需要额外的代码了。
我们引入Spring中的事务与MyBatis-Spring的事务管理。一定要记得添加Spring-tx.jar的依赖。修改ApplicationContext.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--属性占位文件引入,可以通过${属性名}获得属性文件中的内容 -->
<context:property-placeholder location="classpath:db.properties" />
<!--定义一个jdbc数据源,创建一个驱动管理数据源的bean -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="acquireIncrement" value="5"></property>
<property name="initialPoolSize" value="10"></property>
<property name="minPoolSize" value="5"></property>
<property name="maxPoolSize" value="20"></property>
</bean>
<!--创建一个sql会话工厂bean,指定数据源 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource" />
<!--指定sql映射xml文件的路径 -->
<property name="mapperLocations"
value="classpath:mapper/*Mapper.xml"></property>
</bean>
<!--自动扫描映射接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定sql会话工厂,在上面配置过的 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!-- 指定基础包,即自动扫描cn.liuw.dao这个包以及它的子包下的所有映射接口类 -->
<property name="basePackage" value="cn.liuw.dao"></property>
</bean>
<!--声明式事务管理 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--声明支持使用注解管理事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
<!--自动扫描组件 -->
<context:component-scan base-package="cn.liuw">
<context:exclude-filter type="aspectj" expression="cn.liuw.dao.*"/>
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
修改UserServiceImpl实现类:
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
@Transactional
public void saveUser(User user) {
System.out.println("开始添加用户...");
userMapper.addUser(user);
System.out.println("结束添加用户...");
}
@Override
public int getUserCount() {
return userMapper.getAllUser().size();
}
}
当然也可以通过XML配置的方式,管理事务(前面已经提到过了)。