Spring学习笔记·整合mybatis

  • 整合mybatis的目的
  1. 为了让spring去实现对mybatis的事务管理。
  2. 业务层对数据访问层的注入
  3. 自动创建SQLSessionFactory对象等

一、环境搭建

pom.xml

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>5.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.3</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.3</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.7.0</version>
		</dependency>
	</dependencies>

applicationContext.xml

<!-- 开启注解支持 -->
<context:annotation-config />
<!-- 指定注解所在的包 让spring去扫描他们 -->
<context:component-scan base-package="com.ttc" />

<!--加载外部属性文件 -->
<context:property-placeholder location="db.properties" /> 
<!--配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
	<property name="driverClassName" value="${jdbc.driver}" />
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
	<property name="maxTotal" value="10" />
	<property name="maxIdle" value="5" />
</bean> 
<!--配置mybatis的SqlSessionFactory,使用mybatis-spring整合包中的 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
<!-- 数据库连接池 -->
	<property name="dataSource" ref="dataSource" />
</bean> 
<!--mapper扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.ttc.dao" />
</bean>

model

public class JdpcPojo {
	private int start;
	private int end;
	// setter getter
}
public class StudentPojo {
	private int id;
	private String name;
	private String sex;
	private int age;
	private String password;
	private int cid;
	//setter getter
}

mapper

@Repository
public interface StudentMapper {
	public StudentPojo selectById(int id);
	public List<StudentPojo> selectAll(JdpcPojo jdpcPojo);
}
<?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.ttc.dao.StudentMapper">
	<resultMap type="com.ttc.pojo.StudentPojo" id="studentBO">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="age" column="age" />
		<result property="sex" column="sex" />
		<result property="password" column="password" />
		<result property="cid" column="cid" />
	</resultMap>
	
	<sql id="BaseColumn">
		id, name, age, sex, password, cid
	</sql>
	
	<select id="selectById" parameterType="int" resultMap="studentBO">
		select <include refid="BaseColumn"/>
		from student where id = #{id}
	</select>
	<select id="selectAll" parameterType="com.ttc.pojo.JdpcPojo" resultMap="studentBO">
		select <include refid="BaseColumn" />
		from student
		limit #{start }, #{end}
	</select>
</mapper>

test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTab {
	@Autowired
	private StudentMapper studentMapper;
	
	@Test
	public void testMybatis() {
		JdpcPojo jdpcPojo = new JdpcPojo();
		jdpcPojo.setStart(0);
		jdpcPojo.setEnd(3);
		List<StudentPojo> list = studentMapper.selectAll(jdpcPojo);
		System.out.println(list);
		
		StudentPojo studentPojo = studentMapper.selectById(1);
		System.out.println(studentPojo);
	}
}

二、事务管理

Spring对事务处理进行了抽象定义,不仅仅是简单的执行commit,rollback。
Spring事务管理主要包括3个接口PlatformTransactionManager、TransactionDefinition、TransactionStatus

  • TransactionDefinition:事务详细信息的封装
    隔离级别、传播、超时、只读。。
  • TransactionStatus:事务具体运行状态
    是否提交、是否完成、是否是新的事务。。
  • PlatformTransactionManager:事务管理器

2.1 事务管理简介

  1. PlatformTransactionManager:继承了上面两个接口
    是 Spring 提供的平台事务管理器,用于管理事务。该接口中提供了三个事务操作方法,具体如下。
  • getTransaction:获取一个事务;
  • commit:提交
  • rollback:回滚

在项目中,Spring 将 xml 中配置的事务详细信息封装到对象TransactionDefinition 中,然后通过事务管理器的 getTransaction() 方法获得事务的状态(TransactionStatus),并对事务进行下一步的操作。

Spring为不同的持久化框架提供了不同事务管理器的接口实现:

事务说明
DataSourceTransactionManager适用于基本的jdbc及MyBatis
HibernateTransactionManager用于整合Hibernate ORM框架
JpaTransactionManagerJavaEE里定的Jpa的持久化ORM框架
JtaTransactionManager使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用
  1. TransactionDefinition:
    TransactionDefinition 接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下。
  • String getName():获取事务对象名称。
  • int getIsolationLevel():获取事务的隔离级别。
  • int getPropagationBehavior():获取事务的传播行为。
  • int getTimeout():获取事务的超时时间。
  • boolean isReadOnly():获取事务是否只读。

事务的传播行为:
是指在同一个方法中,不同操作的前后所使用的事务。
当一个用于操作数据库的方法(dao层方法),执行过程中调用了另一个同样用于操作数据库的方法时,这两个方法之间的事务怎么处理,就是通过传播行为。

传播行为的种类:

属性名称描述
PROPAGATION_REQUIREDrequired支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将创建新事务
PROPAGATION_SUPPORTSsupports支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将以非事务状态执行
PROPAGATION_MANDATORYmandatory支持当前事务。如果 A 方法没有事务,则抛出异常
PROPAGATION_REQUIRES_NEWrequires_new将创建新的事务,如果 A 方法已经在事务中,则将 A 事务挂起
PROPAGATION_NOT_SUPPORTEnot_supported不支持当前事务,总是以非事务状态执行。如果 A 方法已经在事务中,则将其挂起
PROPAGATION_NEVERnever不支持当前事务,如果 A 方法在事务中,则抛出异常
PROPAGATION.NESTEDnested嵌套事务,底层将使用 Savepoint 形成嵌套事务

在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务。通常情况下,数据的查询不会改变原数据,所以不需要进行事务管理,而对于数据的增加、修改和删除等操作,必须进行事务管理。如果没有指定事务的传播行为,则 Spring默认的传播行为是 required。

  1. TransactionStatus:
    TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。其中包含六个操作:
名称说明
void flush()刷新事务
boolean hasSavepoint()获取是否存在保存点
boolean isCompleted()获取事务是否完成
boolean isNewTransaction()获取是否是新事务
boolean isRollbackOnly()获取是否回滚
void setRollbackOnly()设置事务回滚

上述涉及的挂起,意思是开启一个独立的事务,已存在的事务暂停执行,等待新事物之星完毕后继续执行,两个事物不会相互影响。

2.2 手动实现事务

添加jar包:

<!-- 事务管理 -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>5.2.2.RELEASE</version>
	</dependency>

配置bean

<import resource="classpath:mybatisConfig.xml" />
<!-- 事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- 事务的属性定义 -->
<bean class="org.springframework.transaction.support.DefaultTransactionDefinition">
	<!-- 不止包含只读(不止包含查询语句)默认  -->
	<property name="readOnly" value="false" />
	<!-- 隔离级别默认repeat-able -->
	<!-- 事务传递行为 -->
	<property name="propagationBehavior" value="0"/>
	<!-- <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> -->
</bean>

结构:

  • service - dao - mapper

测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTab {
	@Autowired
	private StudentService studentService;
	@Autowired
	private DataSourceTransactionManager manager;
	@Autowired
	private DefaultTransactionDefinition definition;
	
	@Test
	public void testMybatis() {
		TransactionStatus status = manager.getTransaction(definition);
		try {
			StudentPojo studentPojo2 = new StudentPojo();
			studentPojo2.setName("tom");
			studentPojo2.setSex("男");
			studentPojo2.setPassword("password01");
			studentPojo2.setAge(23);
			studentPojo2.setCid(1);
			studentService.insertStudent(studentPojo2);
			int i = 1/0;
			manager.commit(status);
		} catch (Exception e) {
			manager.rollback(status);
		}
	}
}

2.3 事务模板

配置bean

<import resource="classpath:mybatisConfig.xml" />
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- 事务模板 -->
<bean class="org.springframework.transaction.support.TransactionTemplate">
	<property name="transactionManager" ref="transactionManager" />
</bean>

测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTxAuto {
	@Autowired
	private StudentService studentService;
	@Autowired
	private TransactionTemplate template;

	@Test
	public void test() {
		template.execute(new TransactionCallback() {
			public Object doInTransaction(TransactionStatus transactionStatus) {
				StudentPojo studentPojo = studentService.selectStudentById(11);
				System.out.println(studentPojo);
				studentPojo.setName("java");
				studentService.insertStudent(studentPojo);
				int i = 1 / 0;
				return null;
			}
		});
	}
}

2.4 tx名称空间

<!-- 引入 xmlns:tx="http://www.springframework.org/schema/tx" -->
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- tx名称空间 专门处理事务 -->
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="*" propagation="REQUIRED"/>
	</tx:attributes>
</tx:advice>

<aop:config>
	<aop:pointcut expression="execution(* com.ttc.service..*(..))" id="transactionPoint"/>
	<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="transactionPoint"/>
</aop:config>

service方法模拟异常

	public void updateStudent(StudentPojo studentPojo) throws Exception {
		studentMapper.updateStudent(studentPojo);
		int i = 1/0;
	}

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTxName {
	@Autowired
	private StudentService studentService;

	@Test
	public void test() {
		StudentPojo studentPojo = studentService.selectStudentById(11);
		System.out.println(studentPojo);
		studentPojo.setName("java");
		studentService.insertStudent(studentPojo);
	}
}

2.5 注解方式配置

<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- 启动一个用于扫描事务注解的Bean即可 -->
<!-- <tx:annotation-driven transaction-manager="transactionManager"/> -->
<tx:annotation-driven /><!-- 默认会找到名字叫transactionManager的bean -->

service

@Transactional(propagation = Propagation.REQUIRED)
public void updateStudent(StudentPojo studentPojo) {
	studentMapper.updateStudent(studentPojo);
	int i = 1/0;
}

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTransactional {
	@Autowired
	private StudentService studentService;
	@Test
	public void test(){
		StudentPojo studentPojo = studentService.selectStudentById(11);
		System.out.println(studentPojo);
		studentPojo.setName("Java);
		studentService.updateStudent(studentPojo);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SqlHelper.java连接数据库通用类... package org.jdbc.com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class SqlHelper { /** * 设置单例 */ public static SqlHelper instance = new SqlHelper(); /** * 设置单例的一个实例方法 * * @return */ public static SqlHelper getInstance() { if (instance == null) { synchronized (SqlHelper.class) { instance = new SqlHelper(); } } return instance; } /** * 得到MySql连接 * * @return */ public static Connection getMySqlConnection() { Connection conn = null; String url = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=utf-8"; String user = "root"; String password = "root"; String driver="com.mysql.jdbc.Driver"; try { Class.forName(driver); conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { System.out.println("连接数据库出现异常" + e.getMessage()); } return conn; } /** * 得到MMSQL连接 * @return */ public static Connection getMMSQLConnection() { String url = "jdbc:sqlserver://localhost:1433;DatabaseName=jdbc"; String user = "sa"; String password = "sa"; String Driver="com.microsoft.sqlserver.jdbc.SQLServerDriver"; Connection conn = null; try { Class.forName(Driver); conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { System.out.println("连接数据库出现异常" + e.getMessage()); } return conn; } /** * 得到Oracle连接 * @return */ public static Connection getOracleConnection() { String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl"; String user = "scott"; String password = "scott"; String Driver="oracle.jdbc.driver.OracleDriver"; Connection conn = null; try { Class.forName(Driver); conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { System.out.println("连接数据库出现异常" + e.getMessage()); } return conn; } /*** * 释放资源... * * @param rs * @param st * @param conn */ public static void Relesae(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) rs.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值