目前大部分的 Java 互联网项目,都是用 Spring MVC + Spring + MyBatis 搭建平台的。
使用 Spring IoC 可以有效的管理各类的 Java 资源,达到即插即拔的功能;通过 Spring AOP 框架,数据库事务可以委托给 Spring 管理,消除很大一部分的事务代码,配合 MyBatis 的高灵活、可配置、可优化 SQL 等特性,完全可以构建高性能的大型网站。
毫无疑问,MyBatis 和 Spring 两大框架已经成了 Java 互联网技术主流框架组合,它们经受住了大数据量和大批量请求的考验,在互联网系统中得到了广泛的应用。使用 MyBatis-Spring 使得业务层和模型层得到了更好的分离,与此同时,在 Spring 环境中使用 MyBatis 也更加简单,节省了不少代码,甚至可以不用 SqlSessionFactory、 SqlSession 等对象,因为 MyBatis-Spring 为我们封装了它们。
搭建工程结构
1.在【src】下创建4个空包 存放项目的大部分类源文件
·mybatis_spring.dao 放置dao数据层交互处理类
·mybatis_spring.mapper 放置mapper代理接口
·mybatis_spring.pojo 放置Java实体类
·mybatis_spring.test 放置测试类
2.创建源文件夹config 放置资源配置文件
·【config/mybatis】创建名为“SqlMapContext.xml”的mybatis全局配置文件
·【config/spring】创建名为“applicationContext.xml”的spring资源配置文件
·【config/sqlMap】创建名为“UserMapper.xml”的mapper映射文件
·【config】下创建“db.properties”数据源和“log4j.properties”日志配置文件
搭建工程环境
mybatis-spring-1.2.2.jar 整合jar包
编写配置文件
编写spring配置文件(需求编写前的基本配置)
·引入约束
·加载数据源
·配置数据源
·配置sqlSessionFactory
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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" 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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载本地数据源 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 配置数据源 -->
<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>
<!--spring整合mybatis
配置sqlSessionFactory
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
编写mybatis配置文件(需求编写前的基本配置)
·配置settings(根据需要)
·别名定义
·加载映射文件(根据需求,spring做包扫描就不需要加载)
SqlMapConfig.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>
<!-- 数据源交给spring配置 -->
<!-- settings -->
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 将积极加载改为消极加载 -->
<setting name="aggressiveLazyLoading" value="false" />
<!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
<setting name="cacheEnabled" value="true" />
</settings>
<!-- 别名定义 -->
<typeAliases>
<package name="mybatis_spring.pojo" />
</typeAliases>
<!-- 加载映射文件 -->
<mappers>
<!-- 数据库操作配置文件 -->
<mapper resource="" />
</mappers>
</configuration>
编写sqlMap配置文件
·添加数据
·修改数据
·删除数据
·通过id查询数据
·用户名模糊查询数据(建议使用sql片段)
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="test">
<!-- 添加数据 -->
<insert id="insertUser" parameterType="mybatis_spring.pojo.User">
<!-- id自动增长 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT
LAST_INSERT_ID()
</selectKey>
<!-- 插入sql语句 -->
insert into user(username,password) values(#{username},#{password})
</insert>
<!-- 修改数据 -->
<update id="updateUser" parameterType="mybatis_spring.pojo.User">
<!-- 插入修改sql语句 -->
update user set username=#{username}, password=#{password} where id=#{id}
</update>
<!-- 删除数据 -->
<delete id="deleteUser" parameterType="mybatis_spring.pojo.User">
<!-- 插入删除语句 -->
delete from user where id=#{id}
</delete>
<!-- 通过id查询 -->
<select id="findUserById" parameterType="java.lang.Integer" resultType="mybatis_spring.pojo.User">
<!-- 插入查询语句 -->
select * from user where id=#{id}
</select>
<!-- 用户名模糊查询 -->
<select id="findUserByLike" parameterType="java.lang.String" resultType="mybatis_spring.pojo.User">
<!-- 插入查询语句 -->
select * from user where username like '%${value}%'
</select>
</mapper>
编写其他配置文件
db.properties
注意修改schema的名称,例:本人schema的名称为mybatis
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
log4j.properties
# 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和spring的整合方式,一个是原始dao的整合开发,另一个是动态mapper接口加包扫描的整合开发。大部分开发公司都是使用后者开发,所以建议使用后者开发,减少代码的编写量和复杂的资源配置。
原始dao的整合开发
编写pojo层
在mybatis_spring.pojo下创建实体类User.java
package mybatis_spring.pojo;
/**
*
* ClassName: User
* @Description: 数据库user实体类
* @author XHChen
* @date 2018年10月14日 下午6:53:30
*/
public class User {
private int id;
private String username;
private String password;
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + "]";
}
}
编写dao层
·在mybatis_spring.dao下创建dao接口UserDao.java
package mybatis_spring.dao;
import java.util.List;
import mybatis_spring.pojo.User;
/**
*
* ClassName: UserDao
*
* @Description: dao接口
* @author XHChen
* @date 2018年10月15日 上午10:53:10
*/
public interface UserDao {
// 添加
public void insertUser(User user) throws Exception;
// 修改
public void updateUser(User user) throws Exception;
// 删除
public void deleteUser(int id) throws Exception;
// 通过id查询
public User findUserById(int id) throws Exception;
// 简单模糊查询
public List<User> findUserByLike(String name) throws Exception;
}
·在mybatis_spring.dao.impl下创建dao实现类UserDaoImpl.java。
·继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession。
package mybatis_spring.dao.impl;
import java.util.List;
import mybatis_spring.dao.UserDao;
import mybatis_spring.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
/**
*
* ClassName: UserDaoImpl
*
* @Description: dao实现类
* @author XHChen
* @date 2018年10月15日 上午10:59:01
*/
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
@Override
public User findUserById(int id) throws Exception {
// 继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession
SqlSession SqlSession = this.getSqlSession();
// 查询id
User user = SqlSession.selectOne("test.findUserById", 1);
return user;
}
@Override
public void insertUser(User user) throws Exception {
// 继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession
SqlSession sqlSession = this.getSqlSession();
// 插入数据库
sqlSession.insert("test.insertUser", user);
// 提交事务
sqlSession.commit();
// 关闭源
sqlSession.close();
}
@Override
public void updateUser(User user) throws Exception {
// 继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession
SqlSession sqlSession = this.getSqlSession();
// 插入数据库
sqlSession.update("test.updateUser", user);
// 提交事务
sqlSession.commit();
// 关闭源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
// 继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession
SqlSession sqlSession = this.getSqlSession();
// 插入数据库
sqlSession.delete("test.deleteUser", id);
// 提交事务
sqlSession.commit();
// 关闭源
sqlSession.close();
}
@Override
public List<User> findUserByLike(String name) throws Exception {
// 继承SqlSessionDaoSupport,通过this.getSqlSession()创建SqlSession
SqlSession sqlSession = this.getSqlSession();
// 插入数据库
List<User> list = sqlSession.selectList("test.findUserByLike", name);
return list;
}
}
编写配置文件
·在mybatis配置文件SqlMapConfig.xml中加载映射文件sqlMap/UserMapper.xml
<!-- 加载映射文件 -->
<mappers>
<!-- 数据库操作配置文件 -->
<mapper resource="sqlMap/UserMapper.xml" />
</mappers>
·在 spring 配置文件applicationContext.xml中添加UserDao的bean配置,将其中定义的sqlSessionFactory对象当做参数注入进去,这样 UserDaoImpl继承 SqlSessionDaoSupport 类才会起到作用
<!-- 原始dao接口 -->
<bean id="userDao" class="mybatis_spring.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
编写Junit Test Case测试类
在mybatis_spring.test下创建UserDaoImpl.java的Junit Test Case测试类UserDaoImplTest.java
package mybatis_spring.test;
import java.io.IOException;
import java.util.List;
import mybatis_spring.dao.UserDao;
import mybatis_spring.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserDaoImplTest {
// 创建会话工厂
private ApplicationContext applicationContext;
// 创建bean
private UserDao userDao;
@Before
/**
*
* @Description: 加载配置文件
* @param @throws IOException
* @return void
* @throws
* @author XHChen
* @date 2018年10月14日 下午9:50:19
*/
public void setUp() throws IOException {
// 定义核心配置文件
applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
userDao = (UserDao) applicationContext.getBean("userDao");
}
@Test
/**
*
* @Description: 添加数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午2:58:11
*/
public void testInsertUser() throws Exception {
// 创建实体类
User user = new User();
user.setUsername("XHChen_06");
user.setPassword("ID9527");
// 调用接口方法
userDao.insertUser(user);
}
@Test
/**
*
* @Description: 更新数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:01:09
*/
public void testUpdateUser() throws Exception {
// 创建实体类
User user = new User();
user.setId(18);
user.setUsername("XHChen_06");
user.setPassword("ID9532");
// 调用接口方法
userDao.updateUser(user);
}
@Test
/**
*
* @Description: 删除数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:03:42
*/
public void testDeleteUser() throws Exception {
// 调用接口方法
userDao.deleteUser(18);
}
@Test
/**
*
* @Description: 通过id查询,继承SqlSessionDaoSupport
* @param @throws Exception
* @return void
* @throws
* @author XHChen
* @date 2018年10月14日 下午9:50:08
*/
public void testfindUserById() throws Exception {
// 查询操作
User user = userDao.findUserById(1);
System.out.println(user);
}
@Test
/**
*
* @Description: 根据名称查询
* @param @throws Exception
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:14:59
*/
public void testFindUserByLike() throws Exception {
// 查询操作
List<User> list = userDao.findUserByLike("XHChen");
for (User user : list) {
System.out.println(user);
}
System.out.println(list.size());
}
}
动态代理 + 包扫描的整合开发
注意(重要):动态代理的开发规范可参考本博主的另一篇文章
编写mapper接口
在mybatis_spring.mapper下创建映射文件UserMapper.xml
·namespace代理接口的路径
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="mybatis_spring.mapper.UserMapper">
<!-- 添加数据 -->
<insert id="insertUser" parameterType="mybatis_spring.pojo.User">
<!-- id自动增长 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT
LAST_INSERT_ID()
</selectKey>
<!-- 插入sql语句 -->
insert into user(username,password) values(#{username},#{password})
</insert>
<!-- 修改数据 -->
<update id="updateUser" parameterType="mybatis_spring.pojo.User">
<!-- 插入修改sql语句 -->
update user set username=#{username}, password=#{password} where id=#{id}
</update>
<!-- 删除数据 -->
<delete id="deleteUser" parameterType="mybatis_spring.pojo.User">
<!-- 插入删除语句 -->
delete from user where id=#{id}
</delete>
<!-- 通过id查询 -->
<select id="findUserById" parameterType="java.lang.Integer" resultType="mybatis_spring.pojo.User">
<!-- 插入查询语句 -->
select * from user where id=#{id}
</select>
<!-- 用户名模糊查询 -->
<select id="findUserByLike" parameterType="java.lang.String" resultType="mybatis_spring.pojo.User">
<!-- 插入查询语句 -->
select * from user where username like '%${value}%'
</select>
</mapper>
编写mapper配置文件
在mybatis_spring.mapper下创建代理接口UserMapper.java
·添加数据
·修改数据
·删除数据
·通过id查询数据
·用户名模糊查询数据(建议使用sql片段)
UserMapper.java
package mybatis_spring.mapper;
import java.util.List;
import mybatis_spring.pojo.User;
/**
*
* ClassName: UserMapper
*
* @Description: 实现pojo的User接口
* @author XHChen
* @date 2018年10月14日 下午9:48:48
*/
public interface UserMapper {
// 添加
public void insertUser(User user) throws Exception;
// 修改
public void updateUser(User user) throws Exception;
// 删除
public void deleteUser(int id) throws Exception;
// 通过id查询
public User findUserById(int id) throws Exception;
// 简单模糊查询
public List<User> findUserByLike(String name) throws Exception;
}
编写spring配置文件
在applicationContext.xml配置文件中配置mapper批量扫描器类
·mapper包中扫描出Mapper接口,自动创建代理对象并且在spring容器中注入。
·自动扫描出来的Mapper的bean的id为 mapper 类名(首字母小写)。
<!-- mapper批量扫描 ,扫描包下的mapper文件,自动创建代理对象-->
<!-- id:根据mapper的实体类名自动获得(首字母小写)
遵循规范:mapper.java和mapper.xml的名称保持一致且在同目录下
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描包下组件 -->
<property name="basePackage" value="mybatis_spring.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
编写Junit Test Case测试类
在mybatis_spring.test下创建UserMapper.java的Junit Test Case测试类UserMapperTest.java
package mybatis_spring.test;
import java.io.IOException;
import java.util.List;
import mybatis_spring.mapper.UserMapper;
import mybatis_spring.pojo.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserMapperTest {
// 创建会话工厂
private ApplicationContext applicationContext;
// 创建bean
private UserMapper userMapper;
@Before
/**
*
* @Description: 加载配置文件
* @param @throws IOException
* @return void
* @throws
* @author XHChen
* @date 2018年10月14日 下午9:50:19
*/
public void setUp() throws IOException {
// 定义核心配置文件
applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
// 获得bean对象
userMapper = (UserMapper) applicationContext.getBean("userMapper");
}
@Test
/**
*
* @Description: 添加数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:33:01
*/
public void testInsertUser() throws Exception {
// 创建实体类
User user = new User();
user.setUsername("XHChen_06");
user.setPassword("ID9527");
// 调用接口方法
userMapper.insertUser(user);
}
@Test
/**
*
* @Description: 更新数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:34:42
*/
public void testUpdateUser() throws Exception {
// 创建实体类
User user = new User();
user.setId(19);
user.setUsername("XHChen_06");
user.setPassword("ID9532");
// 调用接口方法
userMapper.updateUser(user);
}
@Test
/**
*
* @Description: 删除数据库数据
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:35:49
*/
public void testDeleteUser() throws Exception {
// 调用接口方法
userMapper.deleteUser(19);
}
@Test
/**
*
* @Description: 通过id查询,动态代理接口
* @param @throws Exception
* @return void
* @throws
* @author XHChen
* @date 2018年10月14日 下午9:50:08
*/
public void testfindUserById() throws Exception {
// 查询操作
User user = userMapper.findUserById(16);
System.out.println(user);
}
@Test
/**
*
* @Description: 根据名称查询
* @param
* @return void
* @throws
* @author XHChen
* @date 2018年10月15日 下午3:36:37
*/
public void testFindUserByLike() throws Exception {
// 查询操作
List<User> list = userMapper.findUserByLike("XHChen");
for (User user : list) {
System.out.println(user);
}
System.out.println(list.size());
}
}