首页 > 代码库 > mybatis 3.2.7 与 spring mvc 3.x、logback整合
mybatis 3.2.7 与 spring mvc 3.x、logback整合
github上有一个Mybatis-Spring的项目,专门用于辅助完成mybatis与spring的整合,大大简化了整合难度,使用步骤:
准备工作:
maven依赖项:
1 <properties> 2 <java-version>1.6</java-version> 3 <spring.version>3.2.8.RELEASE</spring.version> 4 </properties> 5 <dependencies> 6 7 <!-- Spring --> 8 <dependency> 9 <groupId>org.springframework</groupId> 10 <artifactId>spring-core</artifactId> 11 <version>${spring.version}</version> 12 </dependency> 13 14 <dependency> 15 <groupId>org.springframework</groupId> 16 <artifactId>spring-expression</artifactId> 17 <version>${spring.version}</version> 18 </dependency> 19 20 <dependency> 21 <groupId>org.springframework</groupId> 22 <artifactId>spring-beans</artifactId> 23 <version>${spring.version}</version> 24 </dependency> 25 26 <dependency> 27 <groupId>org.springframework</groupId> 28 <artifactId>spring-context</artifactId> 29 <version>${spring.version}</version> 30 </dependency> 31 <dependency> 32 <groupId>org.springframework</groupId> 33 <artifactId>spring-context-support</artifactId> 34 <version>${spring.version}</version> 35 </dependency> 36 <dependency> 37 <groupId>org.springframework</groupId> 38 <artifactId>spring-web</artifactId> 39 <version>${spring.version}</version> 40 </dependency> 41 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-webmvc</artifactId> 45 <version>${spring.version}</version> 46 </dependency> 47 48 <dependency> 49 <groupId>org.springframework</groupId> 50 <artifactId>spring-oxm</artifactId> 51 <version>${spring.version}</version> 52 </dependency> 53 54 <dependency> 55 <groupId>org.springframework</groupId> 56 <artifactId>spring-jdbc</artifactId> 57 <version>${spring.version}</version> 58 </dependency> 59 60 <dependency> 61 <groupId>org.springframework</groupId> 62 <artifactId>spring-tx</artifactId> 63 <version>${spring.version}</version> 64 </dependency> 65 66 <dependency> 67 <groupId>org.springframework</groupId> 68 <artifactId>spring-aop</artifactId> 69 <version>${spring.version}</version> 70 </dependency> 71 72 73 <dependency> 74 <groupId>org.aspectj</groupId> 75 <artifactId>aspectjweaver</artifactId> 76 <version>1.7.3</version> 77 </dependency> 78 79 <dependency> 80 <groupId>aopalliance</groupId> 81 <artifactId>aopalliance</artifactId> 82 <version>1.0</version> 83 </dependency> 84 85 <!-- json --> 86 <dependency> 87 <groupId>org.codehaus.jackson</groupId> 88 <artifactId>jackson-mapper-asl</artifactId> 89 <version>1.9.3</version> 90 </dependency> 91 92 <dependency> 93 <groupId>org.codehaus.jackson</groupId> 94 <artifactId>jackson-jaxrs</artifactId> 95 <version>1.9.9-redhat-2</version> 96 </dependency> 97 98 <!-- logback --> 99 <dependency>100 <groupId>org.slf4j</groupId>101 <artifactId>slf4j-api</artifactId>102 <version>1.7.7</version>103 </dependency>104 105 <dependency>106 <groupId>ch.qos.logback</groupId>107 <artifactId>logback-core</artifactId>108 <version>1.1.2</version>109 </dependency>110 111 <dependency>112 <groupId>ch.qos.logback</groupId>113 <artifactId>logback-classic</artifactId>114 <version>1.1.2</version>115 </dependency>116 117 <dependency>118 <groupId>commons-logging</groupId>119 <artifactId>commons-logging</artifactId>120 <version>1.1.3</version>121 </dependency>122 123 <!-- Servlet -->124 <dependency>125 <groupId>javax.servlet</groupId>126 <artifactId>servlet-api</artifactId>127 <version>2.5</version>128 <scope>provided</scope>129 </dependency>130 131 <!-- oracle -->132 <dependency>133 <groupId>com.oracle</groupId>134 <artifactId>ojdbc6</artifactId>135 <version>11.2.0.3</version>136 </dependency>137 138 <!-- mybatis -->139 <dependency>140 <groupId>org.mybatis</groupId>141 <artifactId>mybatis-spring</artifactId>142 <version>1.2.2</version>143 </dependency>144 145 <dependency>146 <groupId>org.mybatis</groupId>147 <artifactId>mybatis</artifactId>148 <version>3.2.7</version>149 </dependency>150 151 152 </dependencies>
一、先创建entity类
1 package com.cnblogs.yjmyzz.entity; 2 3 import java.io.Serializable; 4 5 public class BasCarrierEntity implements Serializable { 6 7 private static final long serialVersionUID = -971818065984481747L; 8 9 private int recId;10 private int cyear;11 private String carrier;12 13 public int getRecId() {14 return recId;15 }16 17 public void setRecId(int recId) {18 this.recId = recId;19 }20 21 public int getCyear() {22 return cyear;23 }24 25 public void setCyear(int cyear) {26 this.cyear = cyear;27 }28 29 public String getCarrier() {30 return carrier;31 }32 33 public void setCarrier(String carrier) {34 this.carrier = carrier;35 }36 37 public String toString() {38 return "recid:" + recId + ",cyear:" + cyear + ",carrier:" + carrier;39 }40 41 }
这是一个POJO类,没有任何花头.
二、创建Mapper接口
1 package com.cnblogs.yjmyzz.mybatis.mapper; 2 3 import com.cnblogs.yjmyzz.entity.BasCarrierEntity; 4 5 public interface CarrierMapper { 6 7 BasCarrierEntity getCarrierById(int recId); 8 9 void insertCarrier(BasCarrierEntity entity);10 11 void deleteCarrier(BasCarrierEntity entity);12 13 }
相当于传统ORM数据库应用里的DAO层接口
三、定义sql映射文件 BasCarrier.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 3 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 4 5 <mapper namespace="com.cnblogs.yjmyzz.mybatis.mapper.CarrierMapper"> 6 7 <cache /> 8 9 <select id="getCarrierById" resultType="BasCarrierEntity"10 parameterType="int">11 select t.recid recId,t.cyear cyear,t.carrier carrier12 from T_BAS_CARRIER t where13 t.recid = #{recId}14 </select>15 16 <insert id="insertCarrier" parameterType="BasCarrierEntity">17 <selectKey keyProperty="recId" order="BEFORE" resultType="int">18 select seq_t_bas_carrier.nextval as recId from dual19 </selectKey>20 insert into21 t_bas_carrier(recid,cyear,carrier)22 values(#{recId},#{cyear},#{carrier})23 </insert>24 25 <insert id="deleteCarrier" parameterType="BasCarrierEntity">26 delete from27 t_bas_carrier where 1=128 <if test="carrier != null">29 and carrier like #{carrier}30 </if>31 </insert>32 33 </mapper>
以上这三板斧是必不可少的,注:xml中sql语句的id要与mapper接口中的方法名完全相同,这样不用其它任何额外配置,运行时,mybatis就能自动将接口中的方法与sql关联起来。
四、Spring-Database.xml 配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 8 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 9 http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd10 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd11 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"12 default-autowire="byName">13 14 <bean id="dataSource"15 class="org.springframework.jdbc.datasource.DriverManagerDataSource">16 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />17 <property name="url" value="${db-url}" />18 <property name="username" value="${db-username}" />19 <property name="password" value="${db-password}" />20 </bean>21 22 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">23 <!-- mybatis主配置文件,不能与后面的mapperLocations/typeAliasesPackage同时使用 -->24 <!-- <property name="configLocation" value="http://www.mamicode.com/classpath:mybatis-config.xml"></property> -->25 <property name="dataSource" ref="dataSource" />26 <!-- mapper中的类型别名 -->27 <property name="typeAliasesPackage" value="com.cnblogs.yjmyzz.entity"></property>28 <!-- mybatis 映射sql xml路径 -->29 <property name="mapperLocations" value="classpath:mybatis/**/*.xml"></property>30 </bean>31 32 <!-- 扫描指定包下的Mapper,自动创建mapper bean实例 -->33 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">34 <property name="basePackage" value="com.cnblogs.yjmyzz.mybatis.mapper" />35 </bean>36 37 <!-- 事务管理 -->38 <bean id="transactionManager"39 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">40 <property name="dataSource" ref="dataSource" />41 </bean>42 43 <tx:advice id="txAdvice" transaction-manager="transactionManager">44 <tx:attributes>45 <!-- 仅do开头的Service层方法,发生Exception异常时,才会事务回滚 -->46 <tx:method name="do*" read-only="false" rollback-for="java.lang.Exception" />47 <!-- 其它方法,只读事务,不回滚 -->48 <tx:method name="*" propagation="SUPPORTS" read-only="true" />49 </tx:attributes>50 </tx:advice>51 52 <aop:config>53 <!-- 仅拦截service层方法 -->54 <aop:pointcut id="pc"55 expression="execution(* com.cnblogs.yjmyzz.service..*.*(..))" />56 <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" />57 </aop:config>58 59 <!-- <tx:annotation-driven /> -->60 </beans>
真正属于mybatis专用的配置是22-35行,其它都是些db开发的常规配置。
事务这里有一个要特别注意的问题:因为Spring/SpringMVC的父子容器问题,默认情况下@Service的xxxService并不具备增加事务处理能力,需要做点特殊配置
a) spring-mvc servlet的配置文件里,参考下面配置:
1 <context:component-scan base-package="com.cnblogs.yjmyzz">2 <context:exclude-filter type="annotation"3 expression="org.springframework.stereotype.Service" />4 </context:component-scan>
即:将@Service所对应的Service类排除掉,因为Spring-MVC compent-scan注入的只是普通的bean,不具备增加事务处理能力,所以要排除掉.
b) spring 主配置文件里,参考下面配置:
<context:component-scan base-package="com.cnblogs.yjmyzz"> </context:component-scan>
这样处理后,compent-scan扫描到的Service类,就交由Spring,而非Spring-MVC来注入了。
另外还有一个事务自动提交的问题,虽然在配置中已经明确指定了仅Service层do开头的方法,才支持可写事务,其它方法都是只读事务,但如果你运行一下会发现,其它非do开头的方法如果执行一条insert语句,仍然会提交成功。
造成这个的原因不在于datasource,这里我们采用的是org.springframework.jdbc.datasource.DriverManagerDataSource数据源,这种数据源不支持defaultAutoCommit属性,如果不想使用自动提交,可以把datasource节点换成
1 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 2 destroy-method="close"> 3 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 4 <property name="url" value="${db-url}" /> 5 <property name="username" value="${db-username}" /> 6 <property name="password" value="${db-password}" /> 7 <property name="defaultAutoCommit" value="false" /> 8 <property name="initialSize" value="2" /> 9 <property name="maxActive" value="5" />10 <property name="maxWait" value="60000" />11 </bean>
注意第7行,defaultAutoCommit设置成false即可
如果使用Oracle,事务这里还有一个小坑,read-only不管设置成true/false,效果都是一样的,原因见:http://docs.oracle.com/cd/B19306_01/java.102/b14355/apxtips.htm
Transaction Isolation Levels and Access Modes
Read-only connections are supported by the Oracle server, but not by the Oracle JDBC drivers.
即:使用oracle jdbc驱动时,不支持read-only属性
五、mybatis在eclipse控制台显示sql语句的问题
mybatis支持多种日志组件,默认顺序如下:
• SLF4J
• Apache Commons Logging
• Log4j 2
• Log4j
• JDK logging
而上一篇刚学习的logback组件,正好是SLF4J的实现之一,所以如果采用logback来记录日志,mybatis不用做任何额外配置,将logback.xml扔在resource目录下即可
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <configuration scan="true" scanPeriod="1800 seconds" 3 debug="false"> 4 5 <property name="USER_HOME" value="logs" /> 6 <property scope="context" name="FILE_NAME" value="mybatis-logback" /> 7 8 <timestamp key="byDay" datePattern="yyyy-MM-dd" /> 9 10 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">11 <encoder>12 <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n13 </pattern>14 </encoder>15 </appender>16 17 <appender name="file"18 class="ch.qos.logback.core.rolling.RollingFileAppender">19 <file>${USER_HOME}/${FILE_NAME}.log</file>20 21 <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">22 <fileNamePattern>${USER_HOME}/${byDay}/${FILE_NAME}-${byDay}-%i.log.zip23 </fileNamePattern>24 <minIndex>1</minIndex>25 <maxIndex>10</maxIndex>26 </rollingPolicy>27 28 <triggeringPolicy29 class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">30 <maxFileSize>5MB</maxFileSize>31 </triggeringPolicy>32 <encoder>33 <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n34 </pattern>35 </encoder>36 37 </appender>38 39 <logger name="com.cnblogs.yjmyzz" level="debug" additivity="true">40 <appender-ref ref="file" />41 <!-- <appender-ref ref="STDOUT" /> -->42 </logger>43 44 <root level="debug">45 <appender-ref ref="STDOUT" />46 </root>47 </configuration>
注:log的level要设置成DEBUG。
logback与spring mvc整合的方法,上一篇已经讲过,就不再重复了,这里只给出web.xml的配置
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 5 <context-param> 6 <param-name>logbackConfigLocation</param-name> 7 <param-value>classpath:logback.xml</param-value> 8 </context-param> 9 <listener>10 <listener-class>com.cnblogs.yjmyzz.util.LogbackConfigListener</listener-class>11 </listener>12 13 <context-param>14 <param-name>contextConfigLocation</param-name>15 <param-value>classpath:root-context.xml</param-value>16 </context-param>17 <filter>18 <filter-name>CharacterEncodingFilter</filter-name>19 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>20 <init-param>21 <param-name>encoding</param-name>22 <param-value>utf-8</param-value>23 </init-param>24 </filter>25 <filter-mapping>26 <filter-name>CharacterEncodingFilter</filter-name>27 <url-pattern>/*</url-pattern>28 </filter-mapping>29 <listener>30 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>31 </listener>32 <servlet>33 <servlet-name>appServlet</servlet-name>34 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>35 <init-param>36 <param-name>contextConfigLocation</param-name>37 <param-value>classpath:servlet-context.xml</param-value>38 </init-param>39 <load-on-startup>0</load-on-startup>40 </servlet>41 <servlet-mapping>42 <servlet-name>appServlet</servlet-name>43 <url-pattern>/</url-pattern>44 </servlet-mapping>45 46 </web-app>
示例源码:Spring-MVC-REST-MyBatis.zip
mybatis 3.2.7 与 spring mvc 3.x、logback整合