上一篇中我们已经搭建了一个Spring MVC工程,现在我们在此基础上来集成Mybatis。
配置pom.xml
还是到http://mvnrepository.org/上面来找依赖。
spring-jdbc
搜索spring jdbc,我们选用4.3.4版本,依赖如下:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
mysql-connector-java
搜索mysql,找到MySQL Connector/J,我们选用6.0.5版本,依赖如下:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
commons-dbcp
搜索commons dbcp,我们选用1.4版本,依赖如下:
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
mybatis-spring
搜索mybatis spring,我们选用1.3.0,依赖如下:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
mybatis
搜索mybatis,我们选用3.3.0,依赖如下:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
pom.xml完整配置
至此,pom.xml文件就配置好了 ,完整配置如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>mavenSpringDemo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mavenSpringDemo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<build>
<finalName>mavenSpringDemo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建业务代码
创建entity
新建com.demo.entity包,新建User类,(数据库中自然是要建相应的user表,这个这里就不说了。)完整代码如下:
package com.demo.entity;
public class User {
private int id;
private String name;
private String password;
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
}
}
创建DAO接口和实现
新建com.demo.dao包,新建UserDAO接口,完整代码如下:
package com.demo.dao;
import com.demo.entity.User;
public interface UserDAO {
public User selectById(int id);
}
新建com.demo.dao.impl包,新建UserDAOImpl类,完整代码如下:
package com.demo.dao.impl;
import javax.annotation.Resource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.stereotype.Repository;
import com.demo.dao.UserDAO;
import com.demo.entity.User;
@Repository
public class UserDAOImpl extends SqlSessionDaoSupport implements UserDAO {
@Resource
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
@Override
public User selectById(int id) {
return this.getSqlSession().selectOne("com.demo.UserMapper.selectById", id);
}
}
创建Service的接口和实现
新建com.demo.service包,新建UserService接口,完整代码如下:
package com.demo.service;
import com.demo.entity.User;
public interface UserService {
public User selectById(int id);
}
新建com.demo.service.impl包,新建UserServiceImpl类,完整代码如下:
package com.demo.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.demo.dao.UserDAO;
import com.demo.entity.User;
import com.demo.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
public User selectById(int id) {
return userDAO.selectById(id);
}
}
修改Controller
上一篇中我们已经新建了com.demo.web包, 以及UserController类,现在我们修改一下,完整代码如下:
package com.demo.web;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.demo.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/sayHello")
public void sayHello(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.getWriter().write(userService.selectById(1).toString());
}
}
创建Mapper
在resources下新建目录/config/mappers,新建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="com.demo.UserMapper">
<select id="selectById" resultType="com.demo.entity.User">
select * from user where id = #{id}
</select>
</mapper>
配置applicationContext.xml
配置包扫描
我们扫描com.demo包下所有的类,
<context:component-scan base-package="com.demo" />
但是之前在spring-mvc.xml里已经扫描过com.demo.web,这个包里面都是用@Controller注解的controller类,为了不重复扫描,我们把它排除:
<context:component-scan base-package="com.demo">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
配置dataSource
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
配置sessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:config/mappers/**/*.xml" />
</bean>
配置tx:annotation-driven
<tx:annotation-driven transaction-manager="transactionManager" />
配置transactionManager
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
applicationContext.xml完整配置
至此,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: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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.demo">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:config/mappers/**/*.xml" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
配置web.xml
配置contextConfigLocation
<context-param>
<param-name>contextConfigLocation </param-name>
<param-value>classpath:applicationContext.xml </param-value>
</context-param>
配置contextLoaderListener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
web.xml完整配置
web.xml里的其他配置在上一篇中已经配过了,完整配置如下:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation </param-name>
<param-value>classpath:applicationContext.xml </param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
至此,Spring MVC工程集成Mybatis完毕。
测试
测试基本功能
测试一下基本功能,启动tomcat,访问http://localhost:8080/mavenSpringDemo/sayHello,网页上能显示出user相关信息表示测试成功。
测试事务
测试一下事务是否有效。之前我们在applicationContext.xml里已经配置好了事务相关的配置:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
现在我们就增加一些业务代码。
在UserMapper.xml里增加一个方法:
<insert id="insert" parameterType="com.demo.entity.User">
insert user(id, name, password) values(#{id}, #{name}, #{password})
</insert>
在UserDAO.java里增加一个接口方法:
public int insert(User user);
在UserDAOImpl.java里增加一个实现方法:
@Override
public int insert(User user) {
return this.getSqlSession().insert("com.demo.UserMapper.insert", user);
}
在UserService.java里增加一个接口方法:
public int insert(User user);
在UserServiceImpl.java里增加一个实现方法:
@Override
@Transactional
public int insert(User user) {
userDAO.insert(user);
throw new RuntimeException();
}
注意,这个方法上写上@Transactional注解,表示这个方法我们要进行事务的控制。调用insert方法以后直接抛出异常用来测试事务是否有效。如果事务有效,那么insert方法将会回滚,也就是说数据不会插到数据库里去。
在UserController.java里增加方法:
@RequestMapping("/insert")
public void insert(HttpServletResponse response) throws IOException {
User user = new User();
user.setId(10);
user.setName("name10");
user.setPassword("123456");
String result = "";
try {
result = userService.insert(user) + "";
} catch (RuntimeException e) {
result = "roll back";
}
response.getWriter().write(result);
}
最后我们测试一下,启动tomcat,访问http://localhost:8080/mavenSpringDemo/insert,网页上能显示出“roll back”,并且数据库中User表里并没有插入这条数据表示测试事务成功。
常见问题
问题:
在访问页面的时候,如果出现如下错误:
Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (The server time zone value ‘?й???????’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.)
解决方案:
报这个错说明是时区设置有误,需要在applicationContext.xml中配置dataSource时,在url后面加上时区的设置serverTimezone=UTC,url如下:
jdbc:mysql://localhost:3306/test?serverTimezone=UTC
问题:
tomcat启动时报错:Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required
解决方案:
在DAO的实现类或是DAO继承的DAO基类中(在我们的工程中即为UserDAOImpl)加上如下代码:
@Resource
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
问题:
tomcat启动时报错: IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml];
解决方法:
在web.xml中加入这些配置:
<context-param>
<param-name>contextConfigLocation </param-name>
<param-value>classpath:applicationContext.xml </param-value>
</context-param>