IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring整合Mybatis -> 正文阅读

[Java知识库]Spring整合Mybatis

1. 导入依赖


  1. 第一步新建Maven项目
  2. 在pom.xml的<dependencies></dependenies>导入依赖
  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

<?xml version="1.0" encoding="utf8" ?>
<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>
        <!--注入dao-mapper文件信息,如果映射文件和dao接口 同包同名 则此配置可省略-->
<!--        类似与mapper文件在Mybatis-config.xml文件中的注册-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com/lyx/dao/*.xml</value>
            </list>
        </property>
        <!--        为dao-mapper文件中的实体定义缺省包路径
        如:<select id="queryAll" resultType="User">中User类可以不定义包-->
<!--        类似与在Mybatis-config.xml文件中的typeAliases-->
        <property name="typeAliasesPackage" value="com.lyx.entity"></property>
    </bean>

</beans>

2.3 写个UserDao-Mapper.xml映射文件


  • 注意文件头,与Mybatis-config.xml文件头不一致
<?xml version="1.0" encoding="UTF8" ?>
<!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文件中定义的<mapper namespace=“com.lyx.dao.UserDao”/>没有注册
在这里插入图片描述
运行成功
在这里插入图片描述

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">
<!--        dao接口所在的包 如果有多个包,可以用逗号或者分号分隔
 <property name="basePackage" value="com.lyx.dao,com.xmq.dao"></property>
 <property name="basePackage" value="com.lyx.dao;com.xmq.dao"></property>
 -->
        <property name="basePackage" value="com.lyx.dao"></property>
<!--        如果工厂中只有一个SqlSessionFactory的bean,此配置可省略-->
        <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,否则事务控制失败!

在这里插入图片描述

代码如下:

<!--    引入一个事务管理,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

3.2 配置事务通知


在这里插入图片描述

  • 基于刚刚的事务管理器,我们为其配置一个事务通知,生成一个额外功能,advice,此advice可以切入任何需要事务的方法,通过事务管理器为方法控制事务
  • 代码如下
    <!--引入一个事务管理,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
    <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文件所有内容

<?xml version="1.0" encoding="utf8" ?>
<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>
        <!--注入dao-mapper文件信息,如果映射文件和dao接口 同包同名 则此配置可省略-->
<!--        类似与mapper文件在Mybatis-config.xml文件中的注册-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com/lyx/dao/*.xml</value>
            </list>
        </property>
        <!--        为dao-mapper文件中的实体定义缺省包路径
        如:<select id="queryAll" resultType="User">中User类可以不定义包-->
<!--        类似与在Mybatis-config.xml文件中的typeAliases-->
        <property name="typeAliasesPackage" value="com.lyx.entity"></property>
    </bean>
    <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--        dao接口所在的包 如果有多个包,可以用逗号或者分号分隔
 <property name="basePackage" value="com.lyx.dao,com.xmq.dao"></property>
 <property name="basePackage" value="com.lyx.dao;com.xmq.dao"></property>
 -->
        <property name="basePackage" value="com.lyx.dao"></property>
<!--        如果工厂中只有一个SqlSessionFactory的bean,此配置可省略-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
      </bean>
    <!--引入一个事务管理,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
    <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>
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-30 08:33:07  更:2022-04-30 08:33:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:05:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码