整合 spring 4(包括mvc、context、orm) + mybatis 3 示例

来源:互联网 发布:医疗器械软件研究 编辑:程序博客网 时间:2024/05/22 02:27
作者各必备工具的版本如下:
  1. MySQL:5.6.25-log MySQL Community Server (GPL) (下载地址)
  2. Tomcat:apache-tomcat-7.0.63 (下载链接)
  3. Java EE - Eclipse:Luna Service Release 1 v4.4.1 (下载链接)
  4. Spring:4.2.0.RELEASE (无须下载)
  5. MyBatis:3.3.0 (无须下载)
  6. JDK:1.7.0_67 (下载链接)

项目搭建

第三方包依赖 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/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>bdp</groupId><artifactId>bdp</artifactId><version>1.0.0</version><packaging>war</packaging><name>bdp</name><description>Basic Data Platform</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.2.0.RELEASE</spring.version></properties><dependencies><!-- spring mvc related.....start --> <!-- TODO: replace jackson with fastjson --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.3</version></dependency><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.9.13</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.6.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.6.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.6.1</version></dependency><!-- spring mvc related.....end --><!-- mybatis orm related.....start --><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.2.3</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.36</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.3.0</version></dependency><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><!-- mybatis orm related.....end --><!-- project log related.....start --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- project log related.....end --></dependencies><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.7</source><target>1.7</target></configuration></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>2.4</version><configuration><warSourceDirectory>WebContent</warSourceDirectory><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin></plugins></build></project>

测试用表 CITY_CODE_CN:
CREATE TABLE `CITY_CODE_CN` (  `ID` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',  `CITY_CODE` CHAR(4) NOT NULL COMMENT '城市代码》四位阿拉伯数字',  `CITY_JB` TINYINT UNSIGNED NOT NULL COMMENT '城市级别》非空。1:省级;2:地级;3:县级',  `PROVINCE_CODE` CHAR(4) NOT NULL COMMENT '所在省份代码》非空',  `STATE` CHAR(1) NOT NULL DEFAULT '1' COMMENT '城市状态》非空。0:无效城市;1:有效城市',  `CITY_NAME` VARCHAR(50) NOT NULL COMMENT '城市名称',  `CITY` VARCHAR(50) NOT NULL COMMENT '所在地级市名称',  `PROVINCE` VARCHAR(50) NOT NULL COMMENT '所在省份名称',  PRIMARY KEY (`ID`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8 COMMENT '全国城市表';

注意存储引擎不可以是不支持事务的 MyISAM(InnoDB 和 MyISAM 的区别参考博客《MySql 存储引擎的选取》)。
表 CITY_CODE_CN 映射到的 xml 文件 com.defonds.bdp.city.mapper.CityMapper.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.defonds.bdp.city.mapper.CityMapper" >       <insert id="insertCity" parameterType="com.defonds.bdp.city.bean.City">    insert into city_code_cn (city_code, city_jb, province_code, city_name, city, province)        values ( #{cityCode,jdbcType=CHAR}, #{cityJb,jdbcType=INTEGER}, #{provinceCode,jdbcType=CHAR},        #{cityName,jdbcType=VARCHAR}, #{city,jdbcType=VARCHAR}, #{province,jdbcType=VARCHAR} )    </insert></mapper>

表 CITY_CODE_CN 映射到的 java 文件 com.defonds.bdp.city.bean.City.java:
/** * File Name:City.java * * Copyright Defonds Corporation 2015  * All Rights Reserved * */package com.defonds.bdp.city.bean;import org.codehaus.jackson.map.annotate.JsonSerialize;import com.fasterxml.jackson.databind.PropertyNamingStrategy;import com.fasterxml.jackson.databind.annotation.JsonNaming;/** *  * Project Name:bdp * Type Name:City * Type Description: * 1. annotation @JsonSerialize, Entity serialized to json * 2. annotation @JsonNaming, convert Higher case to under score  * and Lower case, example: cityCode,  * after json naming convert, will be city_code * Author:Defonds * Create Date:2015-08-28 * @version  *  */@JsonSerialize@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)  public class City {private String id;private String cityCode;private String provinceCode;private String cityName;private String cityJb;private String city;private String province;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getCityCode() {return cityCode;}public void setCityCode(String cityCode) {this.cityCode = cityCode;}public String getCityName() {return cityName;}public void setCityName(String cityName) {this.cityName = cityName;}public String getCityJb() {return cityJb;}public void setCityJb(String cityJb) {this.cityJb = cityJb;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getProvinceCode() {return provinceCode;}public void setProvinceCode(String provinceCode) {this.provinceCode = provinceCode;}}

处理所有 MyBatis 的配置文件的配置文件 mybatis-config.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>    <settings>        <setting name="mapUnderscoreToCamelCase" value="true"/>    </settings></configuration>

无须将每个小配置单独导入,mapUnderscoreToCamelCase 是把 db CITY_CODE_CN 的下划线字段和 java 实体 bean 的驼峰标识相互转化。
Spring 上下文配置文件 bdp-applicationContext.xml:
<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-4.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">            <!-- mybatis related... start --><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations"><list><!-- 这里支持多种寻址方式:classpath和file --><value>classpath:jdbc.properties</value><!-- 推荐使用file的方式引入,这样可以将配置和代码分离 --></list></property></bean><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource "destroy-method="close"><property name="driverClass" value="com.mysql.jdbc.Driver" /><property name="jdbcUrl" value="jdbc:mysql://${jdbc.host}:${jdbc.port}/${jdbc.database}?useUnicode=true&amp;characterEncoding=utf8" /><property name="user" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="acquireIncrement" value="1" /><property name="initialPoolSize" value="5" /><property name="maxPoolSize" value="20" /><property name="minPoolSize" value="5" /><property name="maxStatements" value="100" /><property name="testConnectionOnCheckout" value="true" /></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="/WEB-INF/classes/mybatis-config.xml" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">        <property name="basePackage" value="com.defonds.bdp.*.mapper"/>    </bean>    <!-- mybatis related... end --><!-- class annotation related... start --><context:component-scan base-package="com.defonds.bdp.*.service" /><!-- class annotation related... end --><context:annotation-config /><!-- transaction config related... start --><tx:annotation-driven transaction-manager="transactionManager" /><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- transaction config related... end --></beans>

Spring MVC 配置文件 bdpmvc-servlet.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">  <!-- class annotation related... start --><context:component-scan base-package="com.defonds.bdp.*.controller" /><!-- class annotation related... end -->  <!-- jsp page related... start --><bean id="viewResolver"class="org.springframework.web.servlet.view.UrlBasedViewResolver"><property name="viewClass"value="org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean><!-- jsp page related... end --><!-- rest json related... start --><bean id="mappingJacksonHttpMessageConverter"          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">        <property name="supportedMediaTypes">            <list>                <value>application/json;charset=UTF-8</value>            </list>        </property>    </bean>    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">        <property name="messageConverters">            <list>                <ref bean="mappingJacksonHttpMessageConverter"/>            </list>        </property>    </bean>    <!-- rest json related... end --></beans>

将所有 Spring 配置文件注册到 web.xml:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID" version="3.0"><display-name>bdp</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/classes/*-applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>bdpmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/classes/*-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>bdpmvc</servlet-name><url-pattern>*.json</url-pattern><url-pattern>*.html</url-pattern></servlet-mapping></web-app>

数据库连接配置文件 jdbc.properties:
jdbc.host=192.168.1.30jdbc.database=bdpdbjdbc.port=3306jdbc.username=bdpdevjdbc.password=xqder798

log4j 配置文件 log4j.properties:
# Global logging configurationlog4j.rootLogger=WARN,stdoutlog4j.logger.com.defonds=DEBUG log4j.rootLogger=WARN,stdout # Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

测试用 mapper 文件 com.defonds.bdp.city.mapper.CityMapper.java:
/** * File Name:CityMapper.java * * Copyright Defonds Corporation 2015  * All Rights Reserved * */package com.defonds.bdp.city.mapper;import com.defonds.bdp.city.bean.City;/** *  * Project Name:bdp * Type Name:CityMapper * Type Description: * Author:Defonds * Create Date:2015-08-31 * @version  *  */public interface CityMapper {public void insertCity(City city);}

服务层处理类 com.defonds.bdp.city.service.CityService.java:
/** * File Name:CityService.java * * Copyright Defonds Corporation 2015  * All Rights Reserved * */package com.defonds.bdp.city.service;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.defonds.bdp.city.bean.City;import com.defonds.bdp.city.mapper.CityMapper;/** *  * Project Name:bdp * Type Name:CityService * Type Description: * Author:Defonds * Create Date:2015-08-31 * @version  *  */@Service@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public class CityService { private final Log logger = LogFactory.getLog(this.getClass());@Autowiredprivate CityMapper cityMapper;public void insertCity() {City city = new City();city.setCityCode("1100");city.setCityJb("1"); city.setProvinceCode("1100");city.setCityName("天津市");city.setCity("天津市");city.setProvince("天津市");logger.debug("before insert the first city");cityMapper.insertCity(city);logger.debug("after insert the first city, and before insert the second city");cityMapper.insertCity(new City()); // this will throw an exceptionlogger.debug("after insert the second city");}}

最后的是 mvc controller 文件 com.defonds.bdp.city.controller.CityController.java:
/** * File Name:CityController.java * * Copyright Defonds Corporation 2015  * All Rights Reserved * */package com.defonds.bdp.city.controller;import java.util.ArrayList;import java.util.List;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.servlet.ModelAndView;import com.defonds.bdp.city.bean.City;import com.defonds.bdp.city.service.CityService;/** *  * Project Name:bdp * Type Name:CityController * Type Description: * Author:Defonds * Create Date:2015-08-27 * @version  *  */@Controller@RequestMapping("/city")public class CityController {private final Log logger = LogFactory.getLog(this.getClass());@Autowiredprivate CityService cityService;@RequestMapping("/welcome")public ModelAndView helloWorld() { String message = "<br><div style='text-align:center;'>"+ "<h3>********** Hello World, Spring MVC Tutorial</h3>This message is coming from CityController.java **********</div><br><br>";return new ModelAndView("welcome", "message", message);}/** * provinceCities(这里用一句话描述这个方法的作用) * TODO(这里描述这个方法适用条件 – 可选) * TODO(这里描述这个方法的执行流程 – 可选) * TODO(这里描述这个方法的使用方法 – 可选) * TODO(这里描述这个方法的注意事项 – 可选) * @param   name * @param  @return    设定文件 * @return String    DOM对象 * @Exception 异常对象 * @since  CodingExample Ver(编码范例查看) 1.0.0 */ @RequestMapping("/province/cities")@ResponseBodypublic Object provinceCities() {List<City> list = new ArrayList<City>();City city1 = new City();city1.setId("126");city1.setCity("济南市");city1.setCityCode("4510");city1.setCityJb("省级");city1.setCityName("济南市");city1.setProvince("山东省");list.add(city1);City city2 = new City();city2.setId("127");city2.setCity("济南市");city2.setCityCode("4510");city2.setCityJb("县级");city2.setCityName("商河县");city2.setProvince("山东省");list.add(city2);return list;}@RequestMapping("/create")@ResponseBodypublic Integer create() {try {this.cityService.insertCity();return 1;} catch (Exception e) {logger.error(e);}return 0;}}

我们来看一下我们的 dbp 项目结构:
dbp 项目结构.png

事务测试

访问事务测试页面如下:
访问事务测试页面.png
控制台打印日志:
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.service.CityService:45 - before insert the first city
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.mapper.CityMapper.insertCity:54 - ==>  Preparing: insert into city_code_cn (city_code, city_jb, province_code, city_name, city, province) values ( ?, ?, ?, ?, ?, ? ) 
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.mapper.CityMapper.insertCity:54 - ==> Parameters: 1100(String), 1(String), 1100(String), 天津市(String), 天津市(String), 天津市(String)
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.mapper.CityMapper.insertCity:54 - <==    Updates: 1
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.service.CityService:47 - after insert the first city, and before insert the second city
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.mapper.CityMapper.insertCity:54 - ==>  Preparing: insert into city_code_cn (city_code, city_jb, province_code, city_name, city, province) values ( ?, ?, ?, ?, ?, ? ) 
2015-08-31 18:29:13 DEBUG com.defonds.bdp.city.mapper.CityMapper.insertCity:54 - ==> Parameters: null, null, null, null, null, null
2015-08-31 18:29:13 ERROR com.defonds.bdp.city.controller.CityController:97 - org.springframework.dao.DataIntegrityViolationException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'CITY_CODE' cannot be null
### The error may involve com.defonds.bdp.city.mapper.CityMapper.insertCity-Inline
### The error occurred while setting parameters
### SQL: insert into city_code_cn (city_code, city_jb, province_code, city_name, city, province)         values ( ?, ?, ?,         ?, ?, ? )
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'CITY_CODE' cannot be null
; SQL []; Column 'CITY_CODE' cannot be null; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'CITY_CODE' cannot be null

查看 db 的 CITY_CODE_CN 表,没有新记录插入,spring 4 + mybatis 3 成功。

源码下载

本文侧重讲 spring ioc、orm 和 mybatis 的事务集成,有评论问关于 spring mvc 的相关配置,请参考另一篇专门讲 spring mvc 搭建的博客《零基础搭建 spring mvc 4 项目(本文基于 Servlet 3.0)》,本文就是在该文基础上进行进一步添加了 service 和 dao 层的扩展而已。本文示例项目源码已共享到 CSDN 资源,有兴趣的朋友可以去下载下来参考:http://download.csdn.net/detail/defonds/9068147。

参考资料

  • http://edwin.baculsoft.com/2015/01/a-simple-spring-4-and-mybatis-transaction-example/
  • http://zhaozhiming.github.io/blog/2014/11/15/spring4-and-mybatis/
0 0
原创粉丝点击