java-Spring+MyBatis整合

Posted Lazy的笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-Spring+MyBatis整合相关的知识,希望对你有一定的参考价值。

Spring整合MyBatis的思路:

在mybatis中,通过创建一个mybatisUtil类,来连接数据库,创建一个SqlSessionFactory,通过这个工厂来创建SqlSession对象。

在Spring的IoC中,可以将所有的类放在IoC容器中进行管理,所以Spring整合MyBatis就是将这个工厂类放在IoC进行管理。


所需要的jar包

commons-logging-1.1.1.jar

log4j-1.2.17.jar

spring-beans-3.2.13.RELEASE.jar

spring-context-3.2.13.RELEASE.jar

spring-core-3.2.13.RELEASE.jar

spring-expression-3.2.13.RELEASE.jar

aopalliance-1.0.jar

aspectjweaver-1.6.9.jar

spring-aop-3.2.13.RELEASE.jar


mybatis-3.2.2.jar

mybatis-spring-1.2.0.jar

mysql-connector-java-5.1.7-bin.jar

spring-jdbc-3.2.13.RELEASE.jar

spring-tx-3.2.13.RELEASE.jar

commons-dbcp-1.4.jar

commons-pool-1.6.jar


要使用Spring中使用MyBatis,需要在spring的配置文件中定义一些类

sqlSessionFactoryBean

为整合应用提供SqlSession对象资源

SqlSessionTemplate

负责管理MyBatis的SqlSession,调用SQL映射语句,实现对数据库的访问

MapperFactoryBean

根据指定Mapper接口生存Bean实例

MapperScannerConfigurer

根据指定包批量扫描Mapper接口并生存实例



Spring和MyBatis的整合步骤

1、加入Spring和MyBatis的有关jar包

2、建立开发目录结构,创建实体类

3、创建数据访问接口

4、创建数据访问接口的实现类

5、配置SQL映射语句文件

6、配置MyBatis应用配置文件

7、配置Spring应用配置文件


ApplicationContext配置文件

<?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: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.xsd

     http://www.springframework.org/schema/tx

     http://www.springframework.org/schema/tx/spring-tx.xsd

     http://www.springframework.org/schema/aop

     http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置数据源,连接数据库 -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

    <property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&amp;charaterEncoding=utf-8"></property>

    <property name="username" value="root"></property>

    <property name="password" value="@lazy"></property>

    </bean>

    <!-- sqlSessionFactoryBean -->

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

    <!-- 使用数据源 -->

    <property name="dataSource" ref="dataSource"></property>

    <!-- 引入mybatis-config.xml配置文件 -->

    <property name="configLocation" value="classpath:mybatis-config.xml"></property>

    <!-- 引入映射文件 ,可以引入多个-->

    <property name="mapperLocations">

    <list>

    <value>classpath:cn/smbms/dao/user/UserMapper.xml</value>

    </list>

    </property>

    </bean>

    

    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

    <!-- 使用构造注入SqlSessionFactory工厂 -->

    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>

    </bean>

    

    <!-- DAO -->

    <bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">

    <property name="sqlSession" ref="sqlSessionTemplate"></property>

    </bean>

    

</beans>


<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

    <!--  使用构造注入SqlSessionFactory工厂  -->

    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>

    </bean> 

    

    <!-- DAO -->

    <bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">

    <!-- 将SqlSessionTemplate对象传入到业务层实现类中 -->

    <!-- <property name="sqlSession" ref="sqlSessionTemplate"></property> -->

    <!-- 这个是 UserMapperImpl继承了SqlSessionDaoSupport,无需再将SqlSessionTemplate传入进去-->

    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>

    </bean>


public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {

/*这个是构造方法获取SqlSessionTemplate;

private SqlSessionTemplate sqlSession;

public SqlSessionTemplate getSqlSession() {

return sqlSession;

}


public void setSqlSession(SqlSessionTemplate sqlSession) {

this.sqlSession = sqlSession;

}*/

public int cout(){

int count = 0;

count = this.getSqlSession().selectOne("count");

return count;

}


手动编写映射器实现存在的问题

SqlSession.selectList()等方法需要采用字符串指定映射项

sqlSession.selectOne("cn.smbms.dao.user.UserMapper.count")

SqlSession.getMapper()方法需要在每次调用时都实现一次映射器接口

sqlSession.getMapper(UserMapper.class)

能否在IoC容器中始终存在一个映射器接口的实现呢?


采用数据映射器(MpperFactoryBean)的方式完成对数据库操作

1、更加Mapper接口获取Mapper对象,它封装了原有的SqlSession.getMapper()功能的实现

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">

<property name="mapperInterface" value="cn.smbms.dao.user.UserMapper"/>

<property name="sqlSessionFactory" ref="sqlSessionFactory" />

</bean>

<property name="mapperInterface" value="cn.smbms.dao.user.UserMapper"/>指定映射器,只能是接口类型

<property name="sqlSessionFactory" ref="sqlSessionFactory" />注入SqlSessionFactory以提供SqlSessionTemplate实例

映射器对应的SQL映射文件与映射器的路径相同,该映射文件可以自动被MapperFactoryBean解析


若映射很多的话,相应配置项会很多,如何简化配置工作量

MapperScannerConfigurer

自动扫描指定包下的Mapper接口,并将它们直接注册为MapperFactoryBean

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

<property name="basePackage" value="cn.smbms.dao" />

</bean>



<?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: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.xsd

     http://www.springframework.org/schema/tx

     http://www.springframework.org/schema/tx/spring-tx.xsd

     http://www.springframework.org/schema/aop

     http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置数据源,连接数据库 -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

    <property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&amp;charaterEncoding=utf-8"></property>

    <property name="username" value="root"></property>

    <property name="password" value="@lazy"></property>

    </bean>

    <!-- sqlSessionFactoryBean -->

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

    <!-- 使用数据源 -->

    <property name="dataSource" ref="dataSource"></property>

    <!-- 引入mybatis-config.xml配置文件 -->

    <property name="configLocation" value="classpath:mybatis-config.xml"></property>

    <!-- 引入映射文件 ,可以引入多个-->

    <property name="mapperLocations">

    <list>

    <value>classpath:cn/smbms/dao/user/UserMapper.xml</value>

    </list>

    </property>

    </bean>

    

   <!--<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

     使用构造注入SqlSessionFactory工厂

    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>

    </bean>   -->注释掉

    

    <!-- <bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">

    <!-- 将SqlSessionTemplate对象传入到业务层实现类中 -->

    <!-- <property name="sqlSession" ref="sqlSessionTemplate"></property> -->

    <!-- 这个是 UserMapperImpl继承了SqlSessionDaoSupport,无需再将SqlSessionTemplate传入进去-->

    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>

    </bean> -->注释掉

    

    <!-- DAO -->

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

    <!-- 可以调用了dao这个包以及子包下的所有接口文件 -->

<property name="basePackage" value="cn.smbms.dao"></property>

</bean>

    

</beans>


当采用了org.mybatis.spring.mapper.MapperScannerConfigurer这个时就不需要注入将sqlSessionTemplate注入到UserMapperImpl类中,这类直接UserMapperImpl继承SqlSessionDaoSupport就可获得SqlSession对象


<扫描注解定义>

    <!-- DAO -->

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

    <!-- 可以调用了dao这个包以及子包下的所有接口文件 -->

<property name="basePackage" value="cn.smbms.dao"></property>

</bean>

上面接口使用这个,可以使所有的DAO层接口都能装到IoC容器中,使用少量的代码量。

<!-- Service -->

<context:component-scan base-package="cn.smbms.service"></context:component-scan>

业务层使用注解,可以引入DAO层,这样可以简化代码量

@Service("userService")

public class UserServiceImpl implements UserService {

@Autowired

@Qualifier("userMapper")

private UserMapper userMapper;

@Override

public int findUsers() {

return userMapper.count();

}

public UserMapper getUserMapper() {

return userMapper;

}

public void setUserMapper(UserMapper userMapper) {

this.userMapper = userMapper;

}

}


<!-- 事务管理,利用AOP编程管理 -->

<!-- 事务管理器 -->

<bean id="txManager" 

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 事务增强处理类 -->

<tx:advice id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<!-- 利用通配符来寻找 -->

<tx:method name="find*" timeout="1000"/>

<tx:method name="*" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

<aop:config>

<!-- * cn.smbms.service..*.*(..)表示在service包下的类或子包的类,参数任意,定义切入点 -->

<aop:pointcut expression="execution(* cn.smbms.service..*.*(..))" id="pointcut"/>

<!-- 增强 -->

<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>

</aop:config>


声明式事务关注的核心问题是:

对那些方法,采取什么样的事务策略

配置步骤

导入tx和aop命名空间

定义事务管理器Bean,并为其注入数据源Bean

通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则

配置切面,将事务增强与方法切入点组合


propagation:事务传播机制

timeout:事务超时时间,运行事务运行时间,以秒为单位

read-only:事务是否为只读,默认值为false

rollback-for:设定能够触发回滚的异常类型

1、Spring默认只在抛出runtime exception时才标识事务回滚

2、可以通过全限定类名指定需要回滚事务异常,多个类名用逗号分隔

no-rollback-for:设定不触发回滚的异常类型

1、Spring默认checked Exception不会触发事务回滚

2、可以通过全限定类名指定不需要回滚事务异常,多个类名用逗号分隔

no-rollback-for:设定不触发回滚的异常类型


在Spring中配置事务管理类,使用注解实现

在增强的方法上使用注解实现事务管理器

//注释整个方法采取事务控制

@Transactional(propagation=Propagation.REQUIRED)

@Service("userService")

public class UserServiceImpl implements UserService {...;}


使用引用将数据库连接信息引用到Sring配置文件中

数据库连接信息写在属性文件中

采用PropertPlaceholderConfigurer可以引入属性文件,在Spring配置文件中采用诸如${url}方式引用属性值

原始方法是直接在配置文件中配置

    <!-- 配置数据源,连接数据库 -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

    <property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&amp;charaterEncoding=utf-8"></property>

    <property name="username" value="root"></property>

    <property name="password" value="@lazy"></property>

    </bean>


使用引用文件

<!-- 使用PropertyPlaceholderConfigurer引入数据库配置文件 -->

     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

      <property name="location">

      <value>classpath:database.properties</value>

      </property>

     </bean>

    <!-- 配置数据源,连接数据库 -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

    <property name="driverClassName" value="${driver}"></property>

    <property name="url" value="${url}"></property>

    <property name="username" value="${user}"></property>

    <property name="password" value="${password}"></property>

    </bean>


通过JNDI从服务器容器中获取DataSource资源

1、在服务器环境配置JNDI数据源

在Tomcat的context.xml文件配置

<Resource name="jndi/smbms" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="10" maxWait="10000" driverClassName="com.mysql.jdbc.Driver" username="root" password="@lazy" url="jdbc:mysql://localhost:3306/smbms?useUnicode=true&amp;charaterEncoding=utf-8" />

2、在Spring配置文件引用JNDI资源

    <!-- 使用JNDI连接数据源 -->

    <bean id="dataSource"  class="org.springframework.jndi.JndiObjectFactoryBean">

    <property name="jndiName">

    <value>java:comp/env/jndi/smbms</value>

    </property>

    </bean>



Spring Bean的作用域及其使用方法

singleton  默认值。Spring以单例模式创建Bean的实例,即容器中该Bean的实例只有一个

prototype 每次从容器中获取Bean时,都会创建一个新的实例

request 用于Web应用环境,针对每次HTTP请求都会创建一个实例

session 用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例

global session 仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境等同于session。

<!-- 指定Bean的作用域为prototype-->scope="prototype"

<bean id="" class=".." scope="prototype">

...

</bean>

使用@Scope注解指定Bean的作用域

@Scope("prototype")

@Service("userService")

public class UserServiceImpl implements UserService{

...}



Spring自动装配

<!--配置业务Bean并注入DAO实例-->

<bean id="userService" class="cn.user.UserServiceImpl">

<property name="userMapper" ref="userMapper" />

</bean>

Spring可以根据属性类型、名称等自动进行注入

设置<bean>元素的autowire属性

<!--配置业务Bean,根据属性名称自动装配-->

<bean id="userService" class="cn.user.UserServiceImpl" aotowire="byName" />


aotowire="byName"

Spring提供的4种自动装配类型

no

byName 根据属性名自动装配。Spring自动查找与属性名相同的id.

byType 根据类型自动装配

constructor 针对构造方法


每个Bean都需要设置aotowire属性,较繁琐

可以为<beans>元素设置default-autowire属性,影响全局

但<bean>节点上aotowire的设置可以覆盖全局设置

<beans default-autowire="byName">

...

</beans>

一般不推荐使用


拆分Spring配置文件

为什么需要拆分配置文件

1、项目规模变大,配置文件可读性、可维护性差

2、团队开发时,多人修改同一配置文件,易发生冲突

拆分策略

1、公用配置+每个系统模块一个单独配置文件(包含DAO、Service、Web控制器)

(适合多人开发,多模块场合)

2、公用配置+DAO Bean配置+业务逻辑Bean配置+Web控制器配置

两种策略各有特色,适用于不同场合


将多个文件合起来

两种方法:

利用ClassPathXmlApplicationContext的重载方法可以配置多个配置文件,用逗号隔开或者使用通配符

public ClassPathXmlApplicationContext(String configLocation);

public ClassPathXmlApplicationContext(String... configLocations);在创建ApplicationContext对象时引入

使用<import resource="xxx.xml" />方式在公共配置文件中引入其他配置文件



以上是关于java-Spring+MyBatis整合的主要内容,如果未能解决你的问题,请参考以下文章

Java-Spring-获取Request,Response对象

Java-Spring JDBC初体验

Java-Spring JDBC初体验

java-Spring 管理bean例子

Java-Spring-获取Request,Response对象

JAVA-Spring AOP详解