作者各必备工具的版本如下:
spring技术学习,更多知识请访问https://www.itkc8.com
- MySQL:5.6.25-log MySQL Community Server (GPL) (下载地址)
- Tomcat:apache-tomcat-7.0.63 (下载链接)
- Java EE - Eclipse:Luna Service Release 1 v4.4.1 (下载链接)
- Spring:4.2.0.RELEASE (无须下载)
- MyBatis:3.3.0 (无须下载)
- JDK:1.7.0_67 (下载链接)
项目搭建
第三方包依赖 pom.xml:
[html] view plain copy print?
- <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:
[sql] view plain copy print?
- 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:
[html] view plain copy print?
- <?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:
[java] view plain copy print?
- /**
- * 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:
[html] view plain copy print?
- <?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:
[html] view plain copy print?
- <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&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:
[html] view plain copy print?
- <?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.xsd
- http://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:
[html] view plain copy print?
- <?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:
[plain] view plain copy print?
- jdbc.host=192.168.1.30
- jdbc.database=bdpdb
- jdbc.port=3306
- jdbc.username=bdpdev
- jdbc.password=xqder798
log4j 配置文件 log4j.properties:
[plain] view plain copy print?
- # Global logging configuration
- log4j.rootLogger=WARN,stdout
- log4j.logger.com.defonds=DEBUG
- log4j.rootLogger=WARN,stdout
- # Console output...
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n
测试用 mapper 文件 com.defonds.bdp.city.mapper.CityMapper.java:
[java] view plain copy print?
- /**
- * 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:
[java] view plain copy print?
- /**
- * 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());
- @Autowired
- private 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 exception
- logger.debug("after insert the second city");
- }
- }
最后的是 mvc controller 文件 com.defonds.bdp.city.controller.CityController.java:
[java] view plain copy print?
- /**
- * 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());
- @Autowired
- private 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")
- @ResponseBody
- public 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")
- @ResponseBody
- public Integer create() {
- try {
- this.cityService.insertCity();
- return 1;
- } catch (Exception e) {
- logger.error(e);
- }
- return 0;
- }
- }
我们来看一下我们的 dbp 项目结构:
事务测试
访问事务测试页面如下:
控制台打印日志:
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。
spring技术学习,更多知识请访问https://www.itkc8.com
参考资料