[ Spring 框架 ] 数据访问和事务管理

目录

[一. spring管理数据访问层](#一. spring管理数据访问层)

[1. spring统一管理数据库连接对象](#1. spring统一管理数据库连接对象)

[(1). 添加 数据访问层 jar 依赖](#(1). 添加 数据访问层 jar 依赖)

[(2). 配置数据库连接对象](#(2). 配置数据库连接对象)

2.spring集成管理mybatis

[(1). 创建service,dao接口,sql映射文件,mybatis配置文件](#(1). 创建service,dao接口,sql映射文件,mybatis配置文件)

[(2) 导入jar](#(2) 导入jar)

[二. AOP 面向切面编程](#二. AOP 面向切面编程)

[1. 定义:](#1. 定义:)

[2. 核心实现(方法):](#2. 核心实现(方法):)

[(1)下载aop aspects框架](#(1)下载aop aspects框架)

(2)添加配置,启动AspectJ注解

(3)创建并配置通知(功能)

[三. Spring事务管理](#三. Spring事务管理)

[1. 定义:](#1. 定义:)

[2. 实现方式:](#2. 实现方式:)

[3. 配置事务管理](#3. 配置事务管理)


一. spring管理数据访问层

以前使用jdbc和mybatis都是由我们自己创建数据库连接的对象

现在使用spring后,可以由spring框架统一管理数据库连接对象,如果在mybatis中需要链接数据库,只需要将spring生成的数据库链接对象注入mybatis

1. spring统一管理数据库连接对象

(1). 添加 数据访问层 jar 依赖
复制代码
<dependencies>
    <!-- spring-context spring最核心功能-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
\<!-- spring-jdbc --\>
\<dependency\>
\<groupId\>org.springframework\</groupId\>
\<artifactId\>spring-jdbc\</artifactId\>
\<version\>5.2.2.RELEASE\</version\>
\</dependency\> \<!-- 阿里数据源 管理对象--\>
\<dependency\>
\<groupId\>com.alibaba\</groupId\>
\<artifactId\>druid\</artifactId\>
\<version\>1.1.10\</version\>
\</dependency\> \<!--mysql jar的坐标--\>
\<dependency\>
\<groupId\>mysql\</groupId\>
\<artifactId\>mysql-connector-java\</artifactId\>
\<version\>8.0.16\</version\>
\</dependency\>
</dependencies>
(2). 配置数据库连接对象

在application.xml中

html 复制代码
<!--配置数据库连接对象
    本次使用的是阿里巴巴提供的Druid(德鲁伊)数据库连接管理类-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/libdb?serverTimezone=Asia/Shanghai"></property>
    <property name="username" value="root"></property>
    <property name="password" value="root"></property>

    <property name="initialSize" value="10"></property><!--初始化连接数量-->
    <property name="maxActive" value="20"></property><!--最大连接数量-->

</bean>

2.spring集成管理mybatis

核心: 将SqlSessionFactory交由Spring管理,并由Spring管理对 dao 接口的代理实现

即不需要在mybatis中添加数据库连接部分,因为spring会数据库连接,如上

(1). 创建service,dao接口,sql映射文件,mybatis配置文件
java 复制代码
package com.ffyc.spring.service;

import com.ffyc.spring.dao.LoginDao;
import com.ffyc.spring.model.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LoginService {
    @Autowired
    private LoginDao loginDao;
    public void login(){
        Admin admin = new Admin();
        admin.setAccount("admin");
        admin.setPassword("111");
        Admin admin1 = loginDao.login(admin);
        System.out.println(admin1);
    }
}
java 复制代码
package com.ffyc.spring.dao;

import com.ffyc.spring.model.Admin;

public interface LoginDao {
    Admin login(Admin admin);
}
XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<!--   xml是一种配置文件,主要用来存储配置文件 -->

<!--  配置全局设置-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

<!-- 为类配置别名 -->
<typeAliases>
<!--    <typeAlias type="com.ffyc.mybatispro.model.Admin"  alias="Admin"/>-->
    <package name="com.ffyc.spring.model"/> <!--    配置模型类的包地址-->
</typeAliases>


</configuration>
(2) 导入jar

<!--mybatis-->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.5.6</version>

</dependency>

<!--spring管理mybatis的jar-->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis-spring</artifactId>

<version>1.3.1</version>

</dependency>

(3) 在application.xml中 配置sqlSessionFactory

html 复制代码
     <!--spring管理sqlSessionFactory对象 ref连接-->
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
     <property name="dataSource" ref="druidDataSource"></property><!--注入数据源-->
     <property name="configLocation" value="classpath:mybatis.xml"></property>
     <property name="mapperLocations" value="classpath:mappers/*Mapper.xml">
     </property>

 </bean>


<!--生成mybatis接口代理对象 直接扫描指定的包-->
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="com.ffyc.spring.dao"></property>
     <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">
     </property>
</bean>

(4)在service层中,注入接口代理对象

java 复制代码
  @Service
public class LoginService {
    @Autowired
    private LoginDao loginDao;
}

二. AOP 面向切面编程

1. 定义:

AOP是对OOP的补充,利用AOP思想,可以将程序中的业务代码和非业代码进行分离 ,降低代码之间的耦合度 ,在增加新功能(非业务代码)时,可以不用修改原来的业务代码.例如 打印日志 , 权限判断 , 事务管理 , 统一异常处理

AOP 的基本概念

**连接点(Joinpoint):**类中可以被增强的方法,这个方法就被称为连接点

**切入点(pointcut):**类中有很多方法可以被增强,但实际中只有 add 和 update

被增了,那么 add 和 update 方法就被称为切入点(实际实现的连接点)

**通知(Advice):**通知是指一个切面在特定的连接点要做的事情(增强的功能)。通

知分为方法执行前通知,方法执行后通知,环绕通知等.

**目标(Target):**代理的目标对象(连接点,切入点所在类)

**代理(Proxy):**向目标对象应用通知时创建的代理对象

2. 核心实现(方法):

为业务代码提供代理对象,可以动态的调用相关的方法,我们只需要做一些简单的配置(告诉代理对象什么时候调用哪个方法)

注意: AOP不是spring框架特有的功能,只是spring将AOP这一思想引用到了自己的框架中,而spring框架中对AOP的具体实现是使用aspectj(AOP)框架

(1)下载aop aspects框架

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aspects</artifactId>

<version>5.2.2.RELEASE</version>

</dependency>

(2)添加配置,启动AspectJ注解

<aop:aspectj-autoproxy />

(3)创建并配置通知(功能)

前置通知,后置通知,环绕通知,异常通知,返回通知.

@Before 前置通知:方法执行之前

@After 后置通知:方法执行之后,无论是否出现异常

@AfterReturnning 返回通知:方法成功执行之后通知,出现异常不执行

@AfterThrowing 异常通知:抛出异常之后通知

@Around 环绕通知:方法执行前后都有通知

java 复制代码
package com.ffyc.spring.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Component
@Aspect
public class Common {
    /*
    通知类型: 前置通知:在目标方法调用之前执行
            后置通知:在目标方法执行完成后执行,即使方法运行时出现异常也会执行
            返回通知:在方法执行完成时执行,方法出现异常就不执行
            异常通知:在方法出现异常时执行
            环绕通知:
     */
   //               *是任意返回值                            *(..)是在BookService中任意参数的方法  ..为方法参数
    @Before("execution(* com.ffyc.spring.service.BookService.*(..))")//@Before 前置通知:方法执行之前
    public void savelog(){
        System.out.println("保存日志1");
    }

    // *.*(..)是在service包中任意类的任意参数方法  ..为方法参数
    @After("execution(* com.ffyc.spring.service.*.*(..))")//@After 后置通知:方法执行之后 即使出现异常也会执行
    public void savelog1(){
        System.out.println("保存日志1");
    }

    // *.*(..)是在service包中任意类的任意参数方法  ..为方法参数
    @AfterReturning("execution(* com.ffyc.spring.service.*.*(..))")// @AfterReturning 出现异常不执行,即没有返回值不执行
    public void savelog2(){
        System.out.println("保存日志2");
    }

    @AfterThrowing(value = "execution(* com.ffyc.spring.service.BookService.*(..))",throwing = "e")//@AfterThrowing 异常通知:抛出异常之后通知
    public void afterthrow(Throwable e){
        System.out.println("系统繁忙"+ e.getMessage());
        e.printStackTrace();
    }


    @Around("execution(* com.ffyc.spring.service.*.*(..))")//@Around 环绕通知:方法执行前后都有通知
    public Object around(ProceedingJoinPoint joinPoint){//joinPoint相当于代理对象
           Object o =null;
        try {
            System.out.println("前置通知");
            //获得目标方法参数
            Object[] args = joinPoint.getArgs();
            System.out.println(Arrays.toString(args));
            o = joinPoint.proceed();//调用自己的目标方法
            System.out.println("返回通知");
        } catch (Throwable e) {
            System.out.println("异常通知");
            e.printStackTrace();
        }
        System.out.println("后置通知");
        return o;
    }

}

三. Spring事务管理

1. 定义:

事务是数据库提供的一种管理机制,要求在同一事物中执行多条sql,要么都执行成功,要么都不执行,称为事务的原子性特征.例如转账

以前在mybatis中, 我们是手动自己提交事务的(sqlsession.commit)

在spring中, 可以在AOP的基础上,让spring中自动的为我们在方法的执行成功时,自动提交事务

2. 实现方式:

(1).编程式事务实现: 需要自己通过事务管理对象,手动提交事务

(2).声明式事务实现: 在方法或类上添加一个注解标签即可, 这样方法在spring事务管理中进行, 方法执行成功测提交事务, 出现异常则回滚事务

3. 配置事务管理

<!-- 配置 spring 事务管理器-->

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

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

</bean>
<!-- 开启注解事务管理 -->

<tx:annotation-driven transaction-manager="transactionManager"/>

在类或方法上使用@Transactional 标签即可.

4. 声明式事务不生效的场景

@Transactional 应用在非 public 修饰的方法上;

异常被 catch 捕获导致失效;

出现编译期异常;

数据库引擎不支持事务;

相关推荐
苍何9 分钟前
30分钟用 Agent 搓出一家跨境网店,疯了
后端
ssshooter23 分钟前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
追逐时光者36 分钟前
一个基于 .NET Core + Vue3 构建的开源全栈平台 Admin 系统
后端·.net
程序员飞哥42 分钟前
90后大龄程序员失业4个月终于上岸了
后端·面试·程序员
zs宝来了1 小时前
Playwright 自动发布 CSDN 的完整实践
java
吴声子夜歌2 小时前
TypeScript——基础类型(三)
java·linux·typescript
GetcharZp3 小时前
Git 命令行太痛苦?这款 75k Star 的神级工具,让你告别“合并冲突”恐惧症!
后端
Victor3563 小时前
MongoDB(69)如何进行增量备份?
后端
Victor3563 小时前
MongoDB(70)如何使用副本集进行备份?
后端