`

springmvc+mybatis初探

 
阅读更多

1.准备jar

 

2.添加springMVC的核心Servlet并设置其初始化加载的配置文件,web.xml内容,内容如下:

<!-- 设置字符编码 -->
<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>GBK</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 配置spring核心控制器 -->
<servlet>
	<servlet-name>dispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring-mvc.xml,classpath:applicationContext-beans.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

 

3.WEB-INF目录中添加spring-mvc.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-3.1.xsd 
						http://www.springframework.org/schema/mvc 
						http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
	<!-- 注解探测器 -->
	<context:component-scan base-package="com.springmvcmybatis" />
	
	<mvc:annotation-driven />
	
	<!-- annotation默认的方法映射适配器 -->
	<!-- 
	<bean id="handlerMapping"
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	<bean id="handlerAdapter"
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
	 -->
	 
 	<!-- 页面View层基本信息设定 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
</beans>

 

4.src目录下添加applicationContext-beans.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

	<!-- 配置DataSource数据源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:oralsb" />
		<property name="username" value="scott" />
		<property name="password" value="tiger" />
	</bean>

	<!-- 配置SqlSessionFactoryBean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:sqlMapConfig.xml" />
		<!-- mapper配置路径 -->
		<property name="mapperLocations">
			<list>
				<value>classpath:com/springmvcmybatis/mapper/*-mapper.xml</value>
			</list>
		</property>
	</bean>

	<!-- 单独配置一个Mapper; 这种模式就是得给每个mapper接口配置一个bean -->
	<!-- 
	<bean id="accountMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
		<property name="mapperInterface" value="com.springmvcmybatis.mapper.AccountMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>
	 -->

	<!-- 自动装配:通过扫描的模式,扫描目录在com/springmvcmybatis/mapper目录下,所有的mapper都继承 SqlMapper接口的接口 -->
	<!-- MapperScannerConfigurer将会创建MapperFactoryBean,之后自动装配 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.springmvcmybatis.mapper" />
		<property name="markerInterface" value="com.springmvcmybatis.mapper.SqlMapper" />
	</bean>

</beans>

 

上面的配置,最先配置的是DataSource,这里采用的是jdbcDataSource;然后是SqlSessionFactoryBean,这个配置比较关键。SqlSessionFactoryBean需要注入DataSource数据源,其次还要设置configLocation也就是mybatisxml配置文件路径,完成一些关于mybatis的配置,如settingsmappersplugin等;

如果使用MapperScannerConfigurer模式,需要设置扫描根路径也就是你的mybatismapper接口所在包路径;凡是markerInterface这个接口的子接口都参与到这个扫描,也就是说所有的mapper接口继承这个SqlMapper

如果你不使用自己的transaction事务,就使用MapperScannerConfigurer来完成SqlSession的打开、关闭和事务的回滚操作。在此期间,出现数据库操作的如何异常都会被转换成DataAccessException,这个异常是一个抽象的类,继承RuntimeException

5.SqlMapper内容如下:

package com.springmvcmybatis.mapper;

public interface SqlMapper {

}

 

6.实体类

package com.springmvcmybatis.model;

public class Account {

	private int accountId;
	private String username;
	private String password;

	// getter、setter

	@Override
	public String toString() {
		return this.accountId + "#" + this.username + "#" + this.password;
	}
}

 

7.src目录中添加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>
	<!-- 别名 -->
	<typeAliases>
		<typeAlias type="com.springmvcmybatis.model.Account" alias="Account" />
	</typeAliases>
</configuration>

 

在这个文件放置一些全局性的配置,如handlerobjectFactoryplugin以及mappers的映射路径(在applicationContext-beans.xml中的SqlSessionFactoryBean有配置mapperlocation,这里就不需要配置)等。

8. AccountMapper接口,内容如下:

package com.springmvcmybatis.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.springmvcmybatis.model.Account;

public interface AccountMapper extends SqlMapper {

	public List<Account> getAllAccount();

	public Account getAccountById(int id);

	public Account getAccountByNames(String name);

	// 这里如果数据库字段名和实体类属性名不对应,需要转换
	@Select("select account_id accountId, username, password from account where username = #{name}")
	public Account getAccountByName(String name);

	public void addAccount(Account account);

	public void updateAccount(Account account);

	public void deleteAccount(int id);

}

 

这个接口我们不需要实现,由mybatis帮助我们实现,我们通过mapper文件配置sql语句即可完成接口的实现。然后这个接口需要继承SqlMapper接口,不然在其他地方就不能从spring容器中拿到这个mapper接口,也就是说当我们注入这个接口的时候将会失败。当然,你不继承这个接口也可以。那就是你需要给每个mapper配置一个bean。配置方法如下:

<bean id="accountMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
	<property name="mapperInterface" value="com.springmvcmybatis.mapper.AccountMapper" />
	<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

 

这里的MapperFactoryBean可以帮助我们完成Session的打开、关闭等操作。

9.com.springmvcmybatis.mapper也就是在AccountMapper接口的同一个包下,添加account-mapper.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">
<!-- namespace和定义的Mapper接口对应,并实现其中的方法 -->
<mapper namespace="com.springmvcmybatis.mapper.AccountMapper">

	<resultMap id="accountResultMap" type="Account">
		<id property="accountId" column="account_id" />
		<result property="username" column="username" />
		<result property="password" column="password" />
	</resultMap>

	<!-- id和mapper接口中的方法名对应 -->
	<select id="getAllAccount" resultType="list" resultMap="accountResultMap">
		SELECT * FROM ACCOUNT
	</select>
	
	<select id="getAccountById" parameterType="int" resultMap="accountResultMap">
		SELECT * FROM ACCOUNT WHERE ACCOUNT_ID = #{id}
	</select>
	
	<select id="getAccountByNames" parameterType="string" resultMap="accountResultMap">
		SELECT * FROM ACCOUNT WHERE USERNAME = #{name}
	</select>
	
	<!-- 自动生成id策略(oralce不支持、mysql和sqlserver支持) -->
	<!-- 
	<insert id="addAccount" useGeneratedKeys="true" keyProperty="account_id" parameterType="Account">
		INSERT INTO ACCOUNT (ACCOUNT_ID, USERNAME, PASSWORD) VALUES (#{accountId}, #{username}, #{password})
	</insert>
	 -->
	
	<!-- 根据selectKey语句生成主键 -->
	<insert id="addAccount" parameterType="Account">
		<selectKey keyProperty="accountId" order="BEFORE" resultType="int">
			SELECT ACCOUNT_SEQ.NEXTVAL FROM DUAL
		</selectKey>
		INSERT INTO ACCOUNT (ACCOUNT_ID, USERNAME, PASSWORD) VALUES (#{accountId}, #{username}, #{password})
	</insert>
	
	<update id="updateAccount" parameterType="Account">
		UPDATE ACCOUNT SET USERNAME = #{username}, PASSWORD = #{password} WHERE ACCOUNT_ID = #{accountId}
	</update>
		
	<delete id="deleteAccount" parameterType="int">
		DELETE FROM ACCOUNT WHERE ACCOUNT_ID = #{id}
	</delete>
	
</mapper>

 

注意:上面的namespace和定义接口类路径必须一致,这里所有的sql语句,如selectinsertdeleteupdateid和方法名称也必须一致。

10.为了测试发布,这里使用junitspring官方提供的org.springframework.test-3.1.4.RELEASE.jar,完成spring框架整合的测试,代码如下:

package com.springmvcmybatis.test;

import javax.annotation.Resource;

import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

import com.springmvcmybatis.mapper.AccountMapper;
import com.springmvcmybatis.model.Account;

@ContextConfiguration("classpath:applicationContext-beans.xml")
public class AccountMapperTest extends AbstractJUnit4SpringContextTests {

	private AccountMapper accountMapper;

	public AccountMapper getAccountMapper() {
		return accountMapper;
	}

	@Resource(name = "accountMapper")
	public void setAccountMapper(AccountMapper accountMapper) {
		this.accountMapper = accountMapper;
	}

	@Test
	public void testGetAccountById() {
		System.out.println(accountMapper.getAccountById(4));
	}

	@Test
	public void testGetAccountByName() {
		System.out.println(accountMapper.getAccountByName("Jack"));
	}

	@Test
	public void testGetAccountByNames() {
		System.out.println(accountMapper.getAccountByNames("Jack"));
	}

	@Test
	public void testAddAccount() {
		Account account = new Account();
		account.setUsername("Jack");
		account.setPassword("abc");
		accountMapper.addAccount(account);
	}

	@Test
	public void testUpdateAccount() {
		Account account = accountMapper.getAccountByNames("Jack");
		System.out.println(account);
		account.setUsername("Tom");
		account.setPassword("123");
		accountMapper.updateAccount(account);
		System.out.println(accountMapper.getAccountById(account.getAccountId()));
	}

	@Test
	public void testDeleteAccount() {
		Account account = accountMapper.getAccountByNames("Tom");
		accountMapper.deleteAccount(account.getAccountId());
		System.out.println(accountMapper.getAccountByNames("Tom"));
	}

	@Test
	public void testGetAllAccount() {
		System.out.println(accountMapper.getAllAccount());
	}

}

 

运行后,没有发现问题,就可以继续后续的编码工作了。

11.定义AccountDao接口

package com.springmvcmybatis.dao;

import java.util.List;

import org.springframework.dao.DataAccessException;

import com.springmvcmybatis.model.Account;

public interface AccountDao {

	public boolean addAccount(Account account) throws DataAccessException;

	public Account getAccountById(int id) throws DataAccessException;

	public List<Account> getAllAccount() throws DataAccessException;

}

 

接口实现

package com.springmvcmybatis.dao.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.springmvcmybatis.dao.AccountDao;
import com.springmvcmybatis.mapper.AccountMapper;
import com.springmvcmybatis.model.Account;

@Component("accountDao")
public class AccountDaoImpl implements AccountDao {

	private AccountMapper accountMapper;

	public AccountMapper getAccountMapper() {
		return accountMapper;
	}

	@Resource(name = "accountMapper")
	public void setAccountMapper(AccountMapper accountMapper) {
		this.accountMapper = accountMapper;
	}

	public boolean addAccount(Account account) throws DataAccessException {
		boolean flag = false;
		try {
			accountMapper.addAccount(account);
			flag = true;
		} catch (DataAccessException e) {
			flag = false;
			throw e;
		}
		return flag;
	}

	public Account getAccountById(int id) throws DataAccessException {
		Account account = null;
		try {
			account = (Account) accountMapper.getAccountById(id);
		} catch (DataAccessException e) {
			throw e;
		}
		return account;
	}

	public List<Account> getAllAccount() throws DataAccessException {
		return accountMapper.getAllAccount();
	}

}

 

12.服务层AccountService接口

package com.springmvcmybatis.service;

import java.util.List;

import org.springframework.dao.DataAccessException;

import com.springmvcmybatis.model.Account;

public interface AccountService {
	public boolean addAccount(Account account) throws DataAccessException;

	public Account getAccountById(int id) throws DataAccessException;

	public List<Account> getAllAccount() throws DataAccessException;
}

 

接口实现

package com.springmvcmybatis.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.springmvcmybatis.dao.AccountDao;
import com.springmvcmybatis.exception.ServiceImplException;
import com.springmvcmybatis.model.Account;
import com.springmvcmybatis.service.AccountService;

@Component("accountService")
public class AccountServiceImpl implements AccountService {

	private AccountDao accountDao;

	public AccountDao getAccountDao() {
		return accountDao;
	}

	@Resource(name = "accountDao")
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}

	public boolean addAccount(Account account) throws DataAccessException {
		if (account == null) {
			throw new ServiceImplException(Account.class.getName() + "对象参数信息为Empty");
		}
		return accountDao.addAccount(account);
	}

	public Account getAccountById(int id) throws DataAccessException {
		return accountDao.getAccountById(id);
	}

	public List<Account> getAllAccount() throws DataAccessException {
		return accountDao.getAllAccount();
	}

}

 

上面用到了一个自定义的异常信息,代码如下:

package com.springmvcmybatis.exception;

import org.springframework.dao.DataAccessException;

public class ServiceImplException extends DataAccessException {

	private static final long serialVersionUID = 1L;

	public ServiceImplException(String msg) {
		super(msg);
	}

	public ServiceImplException(String msg, Throwable cause) {
		super(msg, cause);
	}

}

 

这里只是简单的继承,如果还有其他的异常业务或需求可以进行具体的实现

13.springMVC的控制器,AccountController代码如下:

package com.springmvcmybatis.controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springmvcmybatis.model.Account;
import com.springmvcmybatis.service.AccountService;

@Controller
@RequestMapping("/account")
public class AccountController {

	private AccountService accountService;

	public AccountService getAccountService() {
		return accountService;
	}

	@Resource(name = "accountService")
	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	@RequestMapping("/add")
	public String addAccount(Account account) {
		accountService.addAccount(account);
		return "redirect:/account/list";
	}

	@RequestMapping("/get")
	public String getAccountById(int id, Model model) {
		model.addAttribute(accountService.getAccountById(id));
		return "show";
	}

	@RequestMapping("/list")
	public String getAllAccount(Model model) {
		model.addAttribute("list", accountService.getAllAccount());
		return "list";
	}

	@ExceptionHandler(Exception.class)
	public String exception(Exception e, HttpServletRequest request) {
		request.setAttribute("exception", e);
		return "error";
	}

}

 

14.基本页面代码

/jsp/index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>mybatis-3.2.3整合spring-3.1.4</title>
</head>
<body>
	<h3>mybatis-3.2.3整合spring-3.1.4</h3>
	<a href="account/list">查询所有</a>
	<br />
	<a href="account/add?username=zhangsan&password=123132">添加</a>
	<br />
	<a href="account/get?id=2">查询</a>
	<br />
</body>
</html>

 

/jsp/list.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>all Account Result</title>
</head>
<body>
	<c:forEach items="${list}" var="data">
		id: ${data.accountId }---name: ${data.username }---password: ${data.password }<hr />
	</c:forEach>
</body>
</html>

 

/jsp/show.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>show Account</title>
</head>
<body>
	${account }
	<br />
	${account.username }#${account.password }
</body>
</html>

 

/jsp/error.jsp

<%@ page language="java" import="java.io.PrintWriter" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>Error Page</title>
</head>
<body>
	<H2>Exception: ${exception }</H2>
	<a href="javascript:document.getElementById('show').style.display = 'block';void(0);">详细信息 </a>
	<div id="show" style="color: red; display: none;">
		<%
			Exception e = (Exception) request.getAttribute("exception");
			e.printStackTrace(new PrintWriter(out));
		%>
	</div>
</body>
</html>

 

15.以上就基本上完成了整个SpringMVC+MyBatis的整合了。如果想添加事务管理,得在applicationContext-beans.xml中加入如下配置(service层进行事务管理,这里只配置了addAccount方法的事务管理,有人可能会问这个方法里面只做了一次数据库操作,加事务不是多此一举嘛,声明下,这里纯粹只是为了举例事务的管理配置,在实际项目上,具体的问题还得具体处理)

<!-- 配置事务管理器,注意这里的dataSource和SqlSessionFactoryBean的dataSource要一致,不然事务就没有作用了 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- 定义建议,使用transactionManager事务管理者 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="addAccount" propagation="REQUIRED"/>
	</tx:attributes>
</tx:advice>

<aop:config>
	<!-- 定义一个切入点 -->
	<aop:pointcut id="businessService" expression="execution(public * com.springmvcmybatis.service..*.*(..))"/>
	<aop:advisor pointcut-ref="businessService" advice-ref="transactionAdvice"/>
</aop:config>

 

同时还需要加入aopalliance.jaraspectjweaver.jar两个jar

16.为了查错方便,这里顺便配置下日志文件

web.xml中添加log4j的配置,内容如下:

<!-- Log4j 配置 -->
<context-param>
	<param-name>log4jRefreshInterval</param-name>
	<param-value>60000</param-value>
</context-param>
<listener>
	<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

 

src新建文件log4j.properties,内容如下:

log4j.rootLogger=DEBUG, stdout, fileout
#log4j.logger.test=info
#log4j.logger.org.apache.jasper = DEBUG
#log4j.logger.org.apache.catalina.startup.TldConfig = DEBUG
#log4j.logger.org.apache.catalina.session.ManagerBase = DEBUG

log4j.logger.com.fiscal = DEBUG
log4j.logger.com.system = DEBUG

log4j.logger.com.ibatis = DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource = DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner = DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate = DEBUG
log4j.logger.java.sql.Connection = DEBUG
log4j.logger.java.sql.Statement = DEBUG
log4j.logger.java.sql.PreparedStatement = DEBUG
log4j.logger.java.sql.ResultSet = DEBUG

log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
log4j.appender.fileout.File=C:\\ibatis.log
log4j.appender.fileout.MaxFileSize=10000KB

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %m%n
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout 
log4j.appender.fileout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss} %m%n

 

  • 大小: 17.4 KB
分享到:
评论
1 楼 两好三坏 2014-04-30  
好,写的很细致,我也在学这个

相关推荐

Global site tag (gtag.js) - Google Analytics