Spring整合Mybatis

Spring整合Mybatis,第1张

1. 导入依赖
  1. 第一步新建Maven项目
  2. 在pom.xml的导入依赖
  3. spring核心、mybatis核心、mybatis-spring整合包、log4j日志、common-mysql-java驱动、Druid数据库连接池、spring-orm整合包、Junit测试,具体看这里:Spring框架用到依赖
2. 新建applicationContext.xml文件
2.1 jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3308/companydb?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=20
2.2 配置连接池、SqlSessionFactory

配置DataSource、SqlSessionFactory


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       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.xsd
                           http://www.springframework.org/schema/p
                           http://www.springframework.org/schema/p/spring-p.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd "
>
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.init}"/>
        <property name="maxWait" value="60000"/>
        <property name="timeBetweenEvictionRunsMillis" value="50000"/>
        <property name="minEvictableIdleTimeMillis" value="3000"/>
    bean>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource">property>
        

        <property name="mapperLocations">
            <list>
                <value>classpath:com/lyx/dao/*.xmlvalue>
            list>
        property>
        

        <property name="typeAliasesPackage" value="com.lyx.entity">property>
    bean>

beans>
2.3 写个UserDao-Mapper.xml映射文件
  • 注意文件头,与Mybatis-config.xml文件头不一致

DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyx.dao.UserDao">
    <resultMap id="user_resultMap" type="User">
        <id column="id" property="id">id>
        <result column="username" property="username">result>
        <result column="password" property="password">result>
        <result column="gender" property="gender">result>
        <result column="regist_time" property="registTime">result>
    resultMap>

    <select id="queryUsers" resultMap="user_resultMap">
        select id,username,password,gender,regist_time
        from t_user
    select>
mapper>
2.4 写个测试类
public class TestSpringMybatis {
    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        SqlSessionFactory sqlSessionFactory = (SqlSessionFactory)context.getBean("sqlSessionFactory");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> users = mapper.queryUsers();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

运行报错:.xml文件在编译时不能被编译到测试文件中,所以运行过程中找不到我注册的.xml文件,从而导致我上面再UserDao-Mapper.xml文件中定义的没有注册

运行成功

2.5 配置MapperScannerConfigurer

理解:帮助我们把Mybatis的Dao实现放到工厂中,我们知道,用来mybatis之后,我们是不写UserDaoImpl这种实现类的,我们要想办法把这个实现类对象放到工厂中


作用:管理Dao实现类的创建,并创建Dao对象,存入工厂管理

  1. 扫描所以DAO接口,去构建DAO实现
  2. 将DAO实现存入工厂管理
  3. DAO实现对象在工厂中的id是:“首字母小写的-接口的类名”,例如UserDao==>userDAO,OrderDAO==>orderDAO
    <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <property name="basePackage" value="com.lyx.dao">property>

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
      bean>
2.6 配置Service


    <bean id="userService" class="com.lyx.service.UserServiceImpl">
        <property name="userDao" ref="userDao">property>
    bean>
  • 注意ref中的值是对应DAO接口的首字母小写的接口名
2.7 测试一下

@Test
    public void test2(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserService userService = (UserService)context.getBean("userService");
        List<User> users = userService.queryUsers();
        for (User user : users) {
            System.out.println(user);
        }
    }
3. 事务【重点】
3.1 配置DataSourceTransactionManager
  • 事务管理器,其中ref=dataSource,可以控制事务功能(commit,rollback等)就是对访问或者 *** 作dataSource里面配置的数据库时,进行事务控制
  • 注意DataSourceTransactionManager和SqlSessionFactoryBean要注入同一个DataSource的Bean,否则事务控制失败!

代码如下:


    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

3.2 配置事务通知

  • 基于刚刚的事务管理器,我们为其配置一个事务通知,生成一个额外功能,advice,此advice可以切入任何需要事务的方法,通过事务管理器为方法控制事务
  • 代码如下
    
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

    <tx:advice id="txManager" transaction-manager="tx">
        <tx:attributes>
            <tx:method name="queryUsers" read-only="false" isolation="DEFAULT" rollback-for="Exception"/>
            <tx:method name="query*" propagation="SUPPORTS" timeout="-1" no-rollback-for="Exception"/>
        tx:attributes>
    tx:advice>

  • name里面的query*,意思是所有以query开头的方法,切入事务控制
3.3 事务属性

  • 上面的事务属性的几个标识,依次为只读,事务隔离级别,需要回滚的异常类,事务传播属性,超时(一般不用),不需要回滚的异常类
  • 下面挑几个侧重讲解
3.3.1 隔离级别

isolation


isolation的值有5种:

  • default 默认值
  • read-uncommitted 读未提交
  • read-commited 读提交
  • repeatable-read 可重复读
  • serialized-read 序列化读

以上5种值的隔离级别依次升高!

事务isolation这个属性的作用是什么?事务并发时的安全问题:

  1. 丢失更新(lost update):在完全未隔离事务的情况下,两个事物更新同一条数据资源,如果其中一个事务异常终止,回滚造成第一个完成的更新也同时丢失。
  2. 脏读(dirty read):一个事务查询到另一个事务还未提交的更新数据,read-commited读提交可防止
  3. 幻影读(phantom read):一个事务多次读取,每一次读取结果都不一样,由于是另一个事务在这期间做了插入或者删除了数据造成的。serialized-read可防止
  4. 不可重复读(unrepeated read):一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。repeatable-read 可重复读可防止
  5. 丢失更新2(second lost updates):是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写 *** 作,并提交,第一个事务所做的改变就会丢失。

以上5个值,我们默认使用default,当我们是Mysql数据库,spring默认使用可重复读repeatable-read,当我们是Oracle数据库,spring默认使用读提交read-commited,这两个也是安全性比较高的
如果我们不写isolation属性,默认也是default

3.3.2 传播行为

propagation


  1. 当事务涉及到事务嵌套,Service调用Service时,可以会存在问题
    两个Service层的每个方法都要自己的事务,当Service1中的方法调用了Service2中的方法,就会导致事务的嵌套,如果Service2中的方法发生了错误,该方法事务回滚,但是对调用它的Service1中的方法却没有进行回滚
  2. 传播行为可以为我们解决
  3. 有两个值,SUPPORTS,REQUIRED
  4. SUPPORTS:当不存在外部事务,则该方法也不开启事务,存在外部事务,则合并到外部事务中,比如我们的查询,不对数据库 *** 作,只是查找的话,基本上不会开启事务,所以SUPPORTS适合查询方法使用
  5. REQUIRED:当不存在外部事务,则开启新事务,存在外部事务,则合并到外部事务中,比如我们的增删改,对数据库进行 *** 作,肯定要存在事务控制,所以REQUIRED 适合增删改
3.3.3 timeout事务超时

当事务所需要存在的涉及被其他事务占用,则等待
-1 就是数据库指定等待时间
自定义也可以时间,用到不多

3.3.4 readonly
  1. true 只读,可提供查询效率 ,适合查询
  2. false 可读可写,适合增删改
3.3.5 事务回滚rollback-for
  1. 如果事务中抛出,RuntimeException,则自动回滚
  2. 但是如果事务中抛出,CheckException(非运行时异常 Exception),不会自动回滚,而是默认提交事务
  3. 怎么解决不会自动回滚的异常呢?处理方案:将CheckException转换成RuntimeException上抛,或者 设置 rollback -for=“exception”
3.4 事务编织

将刚刚的事务的Advice的id切入需要事务的业务方法中,这就是Spring的AOP

    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

    <tx:advice id="txManager" transaction-manager="tx">
        <tx:attributes>
            <tx:method name="queryUsers" read-only="false" isolation="DEFAULT" rollback-for="Exception"/>
            <tx:method name="query*" propagation="SUPPORTS" timeout="-1" no-rollback-for="Exception"/>
        tx:attributes>
    tx:advice>
    <aop:config>
        <aop:pointcut id="pc" expression="execution(* com.lyx.service.UserServiceImpl.*queryUsers())"/>
        <aop:advisor advice-ref="txManager" pointcut-ref="pc"/>
    aop:config>

5. applicationContext.xml文件所有内容

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       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.xsd
                           http://www.springframework.org/schema/p
                           http://www.springframework.org/schema/p/spring-p.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd "
>
    <bean id="userService" class="com.lyx.service.UserServiceImpl">
        <property name="userDao" ref="userDao">property>
    bean>
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.init}"/>
        <property name="maxWait" value="60000"/>
        <property name="timeBetweenEvictionRunsMillis" value="50000"/>
        <property name="minEvictableIdleTimeMillis" value="3000"/>
    bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource">property>
        

        <property name="mapperLocations">
            <list>
                <value>classpath:com/lyx/dao/*.xmlvalue>
            list>
        property>
        

        <property name="typeAliasesPackage" value="com.lyx.entity">property>
    bean>
    <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <property name="basePackage" value="com.lyx.dao">property>

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
      bean>
    
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>

    <tx:advice id="txManager" transaction-manager="tx">
        <tx:attributes>
            <tx:method name="queryUsers" read-only="false" isolation="DEFAULT" rollback-for="Exception"/>
            <tx:method name="query*" propagation="SUPPORTS" timeout="-1" no-rollback-for="Exception"/>
        tx:attributes>
    tx:advice>
    <aop:config>
        <aop:pointcut id="pc" expression="execution(* com.lyx.service.UserServiceImpl.*queryUsers())"/>
        <aop:advisor advice-ref="txManager" pointcut-ref="pc"/>
    aop:config>

beans>

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/786918.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存