Spring学习总结(三) ——Spring整合MyBatis (Maven+MySQL)

一、 使用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文件:

 
    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}
    
   

2.2、准备数据

打开MySQL数据库,创建一个表,这里以user表为例。

Spring学习总结(三) ——Spring整合MyBatis (Maven+MySQL)_第1张图片

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 getAllUser();

}

UserMapper.xml文件如下:




    

2.5、创建mybatis-cfg.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

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 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='辽宁大连'}

三、使用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文件如下所示:

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
    
  

 3.2、创建Spring上下文初始化配置文件

该文件取名为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文件中就不需要配置数据源了。




    
        
        
    

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 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接口实例的创建工厂,配置如下:


	
	
	
	

如果有多个表,则需要配置多段信息,麻烦。我们可以通过自动扫描一次完成,配置如下:



	
	
	
	

 需要注意的是这里的sql会话工厂的指定可以使用sqlSessionFactoryBeanName属性指定,也可以使用sqlSessionFactory属性指定,但建议大家使用sqlSessionFactoryBeanName,否则会因为加载的先后顺序问题引起读不到properties文件的内容。

4.2、最终applicationContext.xml文件内容




    
    
    
    
    
        
        
        
        
    

    
    
        
        
        
        
        
        
    
    
    
    
        
        
        
        
    
    
    
    
    

配置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

注意:

  • 如果接口名和xml文件名一致且在一个包下,这里就不需要指定mapperLocations了。

	
	
	
	



	
	
  • applicationContext.xml中指定Mapper.xml位置,可以修改为:在mybatis-cfg.xml中指定

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
#
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配置整合:


	
	
	
	
	
	
	
	

使用上面的代码替换原数据源的创建。

4.3.2、C3P0

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。dbcp没有自动回收空闲连接的功能,而c3p0有自动回收空闲连接功能。

在pom.xml中添加依赖:



	c3p0
	c3p0
	0.9.1.2

在与Spring整合时修改applicationContext.xml,设置如下:



	
	
	
	
	
	
	
	

4.3.3、Druid(德鲁伊)

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项目中启动Spring容器

在Web项目中当Web容器启动时我们要同时启动Spring容器,有三种办法,第一种使用监听器启动,第二使用Servlet启动,第三使用MVC框架的扩展点启动,这里主要选择第一种,因为监听器的启动时机早于Servlet。

使用监听器启动Spring容器

我们需要使用到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启动时的信息,如果没有出现错误且能找到如下说明基本成功。

运行结果:

Spring学习总结(三) ——Spring整合MyBatis (Maven+MySQL)_第2张图片

六、基于注解的声明式事务管理配置

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

你可能感兴趣的:(Spring,FrameWork)