Spring拓展
# Spring拓展
# SpringJDBC实现
Spring 针对数据库开发提供了 JdbcTemplate 类,它封装了 JDBC,支持对数据库的所有操作
JDBC以往的说明:Java学习记录 JDBC篇 (opens new window)
Class JdbcTemplate
org.springframework.jdbc.core.JdbcTemplate
方法
修饰符 | 返回 | 方法 | 说明 |
---|---|---|---|
public | int | update(String sql) | 用于执行新增、修改、删除等语句 |
public | int | update(String sql,Object... args) | 用于执行新增、修改、删除等语句 args 表示需要传入的参数 |
public | void | execute(String sql) | 可以执行任意 SQL,一般用于执行 DDL 语句 action 表示执行完 SQL 语句后,要调用的函数 |
public | T | query(String sql, ResultSetExtractor rse) | 用于执行查询语句 以 ResultSetExtractor 作为参数的 query 方法返回值为 Object |
public | List | query(String sql, RowMapper rse) | 使用查询结果需要对其进行强制转型 以 RowMapper 作为参数的 query 方法返回值为 List |
public | Map<String, Object> | queryForMap(String sql) | SQL查询多个聚合函数结果值,查询出的结果值形式:key-value |
JDBC应用
导入包
spring-jdbc-x.x.x.jar
、spring-tx-x.x.x.jar
以下为个人用Maven配置<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.13.RELEASE</version> </dependency>
Spring-xml配置数据源
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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"> <!-- XML 配置数据源--> <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!--驱动加载--> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <!--连接数据库的url . 本次连接 test库--> <!--指定IP地址 、 库(个人应用的 test库)--> <property name="url" value="jdbc:mysql://192.168.74.131/test"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 配置jdbc模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!--必须使用数据源--> <property name="dataSource" ref="dateSource"/> </bean> <!-- 配置注入类使用--> <bean id="xxx" class="xxx"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <!-- 例如:--> <!-- <bean id="studentDao" class="com.StudentDao">--> <!-- <property name="jdbcTemplate" ref="jdbcTemplate"/>--> <!-- </bean>--> ... </beans>
配置注入类需要自己指定类进行配置
创建实体类
Student
package com; public class Student { int id ; String name; int age; public Student() { } public Student(int id , String name , int age) { this.id = id; this.name = name; this.age = age; } public Student(String name , int age) { this.name = name; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
数据库 test库引入库
id name age DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `age` int(11) NULL DEFAULT 16, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
指定类注入使用
JdbcTemplate类
(应用指定实例 StudentDao;实现一个操作业务即可)package com; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; public class StudentDao extends JdbcDaoSupport { //方法封装 public Student turnEncapsulation(ResultSet resultSet) throws SQLException { Student student = new Student(); student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setAge(resultSet.getInt("age")); return student; } /** * 添加数据 * @param student 学生类封装 * @return 更变条数 */ public int insert(Student student) { if (student == null) { return 0; } String sql = "INSERT INTO student(name,age) VALUE(?,?)"; return this.getJdbcTemplate().update(sql,student.getName(),student.getAge()); } /** * 删除数据 * @param id 删除指定id * @return 更变条数 */ public int delete(int id) { String sql = "DELETE FROM student WHERE id = ?"; return this.getJdbcTemplate().update(sql,id); } /** * 更变数据 * @param id 指定学生id * @param student 更变指定 学生类 * @return 更变条数 */ public int update(int id , Student student) { String sql = "UPDATE student set name=?,age=? WHERE id=?"; return this.getJdbcTemplate().update(sql,student.getName(),student.getAge(),id); } /** * 查询所有条数 * @return 学生队列 */ public List<Student> queryAll(){ String sql = "SELECT * FROM student"; /* 原型 return this.getJdbcTemplate().query(sql , new RowMapper<Student>() { @Override public Student mapRow(ResultSet resultSet , int i) throws SQLException{ System.out.println("\ti : " + i); return turnEncapsulation(resultSet); } }); */ // 简写 return this.getJdbcTemplate().query(sql, (rs,i) -> turnEncapsulation(rs)); } /** * 查询指定学生 * @param id 指定学生id * @return 学生队列 */ public List<Student> queryFindById(int id) { String sql = "SELECT * FROM student WHERE id = ?"; return this.getJdbcTemplate().query(sql,new Object[]{id}, new RowMapper<Student>() { @Override public Student mapRow(ResultSet resultSet , int i) throws SQLException { System.out.println("\ti : " + i); return turnEncapsulation(resultSet); } }); } /** * 查询指定学生名称 * @param name 名称 * @return 学生队列 */ public List<Student> queryFindByName(String name) { String sql = "SELECT * FROM student WHERE name = ?"; //匿名 new RowMapper<Student>() 替换为 lambda return this.getJdbcTemplate().query(sql,new Object[]{name}, (resultSet , i) -> { System.out.println("\ti : " + i); return turnEncapsulation(resultSet); }); } /** * 聚合函数应用 */ /** * 获取学生总数 * @return 学生总数 */ public int tableSize(){ String sql = "SELECT count(id) FROM student"; return this.getJdbcTemplate().queryForObject(sql,Integer.class); } /** * 学生首尾id * @return MAP形式返回id首尾 */ public Map<String , Object> tableMaxMin(){ String sql = "SELECT max(id),min(id) FROM student"; return this.getJdbcTemplate().queryForMap(sql); } }
测试类 (测试业务)
package com; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import java.beans.PropertyVetoException; import java.util.List; import java.util.Map; //连接测试 public class connectionMySQL { ApplicationContext ac = new ClassPathXmlApplicationContext("springJDBC.xml"); StudentDao dao = (StudentDao) ac.getBean("studentDao"); /** * xml应用 */ @Test public void test01_Insert(){ int insert = dao.insert(new Student("老哥" , 23)); System.out.println("insert : " + insert); } @Test public void test02_Delete() { int delete = dao.delete(19); System.out.println("delete : " + delete); } @Test public void test03_Update() { int update = dao.update(16,new Student("黑马",32)); System.out.println("update : " + update); } @Test public void test04_Query() { List<Student> student = dao.queryFindById(17); System.out.println("student : " + student); } @Test public void test04_Querys() { List<Student> students = dao.queryAll(); // List<Student> students = dao.queryFindByName("李四"); for (Student student : students) { System.out.println(student.toString()); } } @Test public void test05_group(){ int i = dao.tableSize(); System.out.println("i : " + i); System.out.println("=============="); Map<String, Object> stringObjectMap = dao.tableMaxMin(); System.out.println("stringObjectMap : " + stringObjectMap); } }
# Spring事务管理
事务(Transaction)是面向关系型数据库(RDBMS)企业应用程序的重要组成部分,用来确保数据的完整性和一致性。
事务了解 :MySQL学习记录 事务篇 (opens new window)
Spring 实现声明式事务管理主要有 2 种方式:
- 基于 XML 方式的声明式事务管理
- 通过 Annotation 注解方式的事务管理
# 事务管理接口
Spring 的事务管理 :PlatformTransactionManager、TransactionDefinition 是事务主要核心接口
PlatformTransactionManager接口
该接口用于管理事务。其主要用于完成事务的提交、回滚,及获取 事务的状态信息
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
返回 | 抽象方法 | 说明 |
---|---|---|
TransactionStatus | getTransaction(@Nullable TransactionDefinition var1) | 获取事务的状态信息 |
void | commit(TransactionStatus var1) | 提交事务 |
void | rollback(TransactionStatus var1) | 回滚事务 |
TransactionDefinition接口
该接口主要获取事务相关信息的作用
public interface TransactionDefinition {
....
default int getPropagationBehavior() {
return 0;
}
default int getIsolationLevel() {
return -1;
}
default int getTimeout() {
return -1;
}
default boolean isReadOnly() {
return false;
}
@Nullable
default String getName() {
return null;
}
....
}
返回 | 抽象方法 | 说明 |
---|---|---|
int | getPropagationBehavior() | 获取事务的 传播行为 |
int | getIsolationLevel() | 获取事务的 隔离级别 |
int | getTimeout() | 获取事务的 超时时间 |
boolean | isReadOnly() | 获取事务是否 只读 |
String | getName() | 获取事务的 名称 |
属性说明
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
传播行为名称值 | 说明 |
---|---|
PROPAGATION_MANDATORY | 支持当前事务,如果不存在当前事务,则引发异常 |
PROPAGATION_NESTED | 如果当前事务存在,则在嵌套事务中执行 |
PROPAGATION_NEVER | 不支持当前事务,如果当前事务存在,则引发异常 |
PROPAGATION_NOT_SUPPORTED | 不支持当前事务,始终以非事务方式执行 |
PROPAGATION_REQUIRED | 默认传播行为,支持当前事务,如果不存在,则创建一个新的 |
PROPAGATION_REQUIRES_NEW | 创建新事务,如果已存在事务则暂停当前事务,应用新的 |
PROPAGATION_SUPPORTS | 支持当前事务,如果不存在事务,则以非事务方式执行 |
# xml应用
主要配置组件(.xml)
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- <tx:method name="insert*" propagation="REQUIRED"/>-->
<!-- <tx:method name="add*" propagation="REQUIRED"/>-->
<!-- <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
应用前提:
添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
实体类:(Student)
package com;
public class Student {
int id ;
String name;
int age;
public Student() {
}
public Student(int id , String name , int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student(String name , int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
StudentDao类:(信息交互类)
package com.dao;
import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class StudentDao extends JdbcDaoSupport {
/**
* 添加数据
* @param student 学生类封装
* @return 更变条数
*/
public int insert(Student student) {
if (student == null) {
return 0;
}
String sql = "insert into student(name,age) value(?,?)";
return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
}
//其他业务操作省略
····
}
StudentService类:(业务处理类)
package com.service;
import com.Student;
import com.dao.StudentDao;
public class StudentService {
private StudentDao studentDao;
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
public int insert(Student student){
int a = studentDao.insert(student);
System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
int aa = 1/0; //制造异常
student.setAge(student.getAge()+1);
int b = studentDao.insert(student);
System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
return a+b;
}
}
Spring 容器配置:(.xml文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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/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
">
<!-- XML 配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl"
value="jdbc:mysql://192.168.6.129:3306/test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 类注入应用-->
<bean id="studentDao" class="com.dao.StudentDao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="studentService" class="com.service.StudentService">
<property name="studentDao" ref="studentDao"/>
</bean>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务触发方法 以及 事务处理方式-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- <tx:method name="insert*" propagation="REQUIRED"/>-->
<!-- <tx:method name="add*" propagation="REQUIRED"/>-->
<!-- <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
</beans>
测试:
@Test
public void test_XML(){
ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig.xml");
StudentService service = (StudentService) ac.getBean("studentService");
//在studentService类 会异常回滚
int number = service.insert(new Student("李四" , 33));
System.out.println("number : " + number);
}
# Annotation应用
主要组件
@Transactional
@Transactional常用属性
属性名 | 说明 |
---|---|
propagation | 配置 事务传播行为 |
isolation | 配置 事务隔离级别 |
readOnly | 配置 事务是否只读 |
timeout | 配置 事务超时事件(单位: s) |
应用前提:
添加事务管理
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
注册加载驱动
<tx:annotation-driven transaction-manager="txManager"/>
应用方法需要添加
@Transactional
注解
实体类:(Student)
package com;
public class Student {
int id ;
String name;
int age;
public Student() {
}
public Student(int id , String name , int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student(String name , int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
StudentDao类:(信息交互类)
package com.dao;
import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class StudentDao extends JdbcDaoSupport {
/**
* 添加数据
* @param student 学生类封装
* @return 更变条数
*/
public int insert(Student student) {
if (student == null) {
return 0;
}
String sql = "insert into student(name,age) value(?,?)";
return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
}
//其他业务操作省略
····
}
StudentService类:(业务处理类)
package com.service;
import com.Student;
import com.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StudentService {
//注入类
@Autowired
private StudentDao studentDao;
//事务配置
@Transactional(propagation = Propagation.REQUIRED , rollbackFor = {Exception.class})
public int insert(Student student){
int a = studentDao.insert(student);
System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
int aa = 1/0; //制造异常
student.setAge(student.getAge()+1);
int b = studentDao.insert(student);
System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
return a+b;
}
}
Spring 容器配置:(.xml文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
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/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
">
<!-- XML 配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--驱动加载-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url . 本次连接 test库-->
<property name="url" value="jdbc:mysql://192.168.6.129/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--扫描包-->
<context:component-scan base-package="com"/>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务应用-->
<bean id="studentDao" class="com.dao.StudentDao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--以注解形式应用-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
测试:
@Test
public void test_Annotation() {
ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig_Annotation.xml");
StudentServic service = (StudentService) ac.getBean("");
int number = service_annotation.insert(new Student("赵六" , 34));
System.out.println("number : " + number);
}