使用Maven创建web项目在此不做赘述了。
要完成使用MyBatis访问MySQL数据库,需要添加一些依赖包,包含MyBatis3,连接驱动,JUnit,Log4j2等。可以去共享资源库中搜索,第一个网站地址是:http://mvnrepository.com/, 这里以搜索连接驱动为示例,搜索后的结果有5.xx版许多,也有6.xx版,但不建议使用6.xx版,因为MyBatis3不支持。
配置pom.xml文件:
UTF-8
1.7
1.7
3.2.8
junit
junit
4.12
test
log4j
log4j
1.2.16
mysql
mysql-connector-java
5.1.35
org.mybatis
mybatis
${mybatis.version}
打开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', '辽宁大连');
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;
}
}
这里用接口+XML的形式完成,User数据访问接口如下:
package cn.liuw.dao;
import cn.liuw.po.User;
import java.util.List;
public interface IUserDao {
/**
* 获得所有图书
*/
public List getAllUser();
}
UserMapper.xml文件如下:
mybatis-cfg.xml文件用于配置MyBatis的运行环境,内容如下:
因为配置中依赖了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
为了更加方便的复用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 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 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='辽宁大连'}
在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来构建应用程序代码。
为了将Spring与MyBatis整合完成,需要依赖MyBatis,因为在上面的示例中已依赖完成,这里就不再需要,主要需依赖的是Spring核心,AOP,JDBC,MyBatis-Spring等jar包。具体的依赖结果pom.xml文件如下所示:
Learning-Spring Maven Webapp
http://www.example.com
UTF-8
1.7
1.7
4.3.1.RELEASE
3.2.8
junit
junit
4.12
test
log4j
log4j
1.2.16
mysql
mysql-connector-java
5.1.35
org.mybatis
mybatis
${mybatis.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-orm
${spring.version}
org.springframework
spring-test
${spring.version}
test
org.springframework
spring-expression
${spring.version}
org.springframework
spring-aop
${spring.version}
org.aspectj
aspectjweaver
1.8.9
commons-dbcp
commons-dbcp
1.2.2
cglib
cglib
3.2.3
该文件取名为ApplicationContext.xml主要原因是“约束优于配置”的理由,使用Web监听器加载Spring时会默认找该名称的文件。在文件中我们可像以前学习Spring一样配置IOC与AOP,只不过这里整合了一些MyBatis内容。文件内容如下:
从上面的代码可以看到分别创建了一个驱动管理数据源的对象,会话工厂与实现数据访问的对象通过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文件中就不需要配置数据源了。
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 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(德鲁伊,阿里巴巴开发)等。
在示例3的applicationContext.xml配置文件中有一段实现IUserDao接口实例的创建工厂,配置如下:
如果有多个表,则需要配置多段信息,麻烦。我们可以通过自动扫描一次完成,配置如下:
需要注意的是这里的sql会话工厂的指定可以使用sqlSessionFactoryBeanName属性指定,也可以使用sqlSessionFactory属性指定,但建议大家使用sqlSessionFactoryBeanName,否则会因为加载的先后顺序问题引起读不到properties文件的内容。
配置mybatis-cfg.xml文件:
创建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 getAllUser();
}
创建mapper下的UserMapper.xml:
测试:
public class Test06 {
@Test
public void demo01(){
//初始化容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获得bean
UserDao userDao = context.getBean(UserDao.class);
//访问数据库
List 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
注意:
通过连接池可以增加数据访问的性能,因为访问数据库时建立连接与释放连接是耗时操作,JDBC默认不带连接池技术,但MyBatis是内置连接池功能的,还有一些第三方知名的连接池技术如:DBCP、C3P0、Druid(德鲁伊)。
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
#
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配置整合:
使用上面的代码替换原数据源的创建。
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。dbcp没有自动回收空闲连接的功能,而c3p0有自动回收空闲连接功能。
在pom.xml中添加依赖:
c3p0
c3p0
0.9.1.2
在与Spring整合时修改applicationContext.xml,设置如下:
Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。阿里巴巴是一个重度使用关系数据库的公司,我们在生产环境中大量的使用Druid,通过长期在极高负载的生产环境中实际使用、修改和完善,让Druid逐步发展成最好的数据库连接池。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。
在与Spring整合时设置:
使用上面的代码替换原数据源的创建。
maven依赖方式:
com.alibaba
druid
1.1.10
github:https://github.com/alibaba/druid,阿里的其它开源框架:https://github.com/alibaba。
在Web项目中当Web容器启动时我们要同时启动Spring容器,有三种办法,第一种使用监听器启动,第二使用Servlet启动,第三使用MVC框架的扩展点启动,这里主要选择第一种,因为监听器的启动时机早于Servlet。
我们需要使用到Spring定义好的一个监听器:org.springframework.web.context.ContextLoaderListener,该监听器在包Spring-web.x.x.x.jar下,修改pom.xml文件,添加依赖:
org.springframework
spring-web
${spring.version}
修改web.xml文件,新增监听器声明,代码如下:
Spring容器启动监听器
org.springframework.web.context.ContextLoaderListener
当监听器在启动Spring容器时会自动查找Web-INF/lib目录下名为applicationContext.xml配置文件,当然也可以设置参数指定配置文件的具体位置,特别是有多个配置文件的情况,指定办法如下:
Spring容器加载监听器
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath*:applicationContext.xml
如果有多个配置文件则可以通过逗号分开。怎么判断是否启动成功,则可以参考本文第二点,获得ApplicationContext实例,也可以查看tomcat启动时的信息,如果没有出现错误且能找到如下说明基本成功。
运行结果:
MyBatis-Spring利用了存在于Spring中的DataSourceTransactionManager管理事务。
一旦Spring的PlatformTransactionManager配置好了,你可以在Spring中以你通常的做法来配置事务。@Transactional注解和AOP方式的配置都是支持的。在事务处理期间,一个单独的SqlSession对象将会被创建和使用。当事务完成时,这个session会以合适的方式提交或回滚。一旦事务创建之后,MyBatis-Spring将会透明的管理事务。在你的DAO类中就不需要额外的代码了。
我们引入Spring中的事务与MyBatis-Spring的事务管理。一定要记得添加Spring-tx.jar的依赖。修改ApplicationContext.xml如下所示:
修改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配置的方式,管理事务(前面已经提到过了)。
参考自:https://www.cnblogs.com/best/p/5646807.htm