SSM---Spring

1、Spring

Spring是一个轻量级框架,Spring致力于Java EE应用的各种解决方案,贯穿表现层,业务层和持久层。并且Spring以高度的开放性与其他原有的框架进行无缝整合。

Spring的整体架构:

Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

SSM---Spring

2、Spring配置

在Spring配置文件中,使用元素来定义Bean的实例。元素有两个常用属性:

  • id:表示定义的Bean实例的名称;
  • class:表示定义的Bean的实例的类型;
<bean id="" class=""/>

通常,Spring为Bean属性赋值时通过调用属性的setter方法实现的。

接着,我们可以通过ClassPathXmlApplicationContext实例化Spring的上下文。

public void test01(){
    ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    User user = context.getBean("user", User.class);
    System.out.println(user.getName());
}

ApplicationContext是一个接口,负责读取Spring配置文件,管理对象的加载、生成、维护Bean对象之间的依赖关系,负责Bean的生命周期等。ClassPathXmlApplicationContext是ApplicationContext接口的实现类,用于从classPath路劲中读取Spring配置文件。

3、依赖注入

3.1 构造器注入

实体类创建有参构造函数:

    public User(String name) {
        this.name = name;
    }

application.xml

<!--  构造器注入  -->
<bean id="userCust" class="com.vxzx.pojo.User">
    <constructor-arg name="name" value="广州"/>
</bean>

3.2 Set方式注入【★】

实体类:

    private String name;
    private Address address;
    private String[] hobbis;
    private List<String> likes;
    private Map<String,String> cid;
    private Set<String> setcontext;
    private Properties por;

application.xml

<!-- 2、复杂类型注入  -->
<bean id="address" class="com.vxzx.pojo.Address">
    <property name="address" value="广东"/>
</bean>

<!-- 1、String注入 -->
<bean id="user1" class="com.vxzx.pojo.User">
    <property name="name" value="vxzx"/>
    <!-- 2、复杂类型注入,需要使用ref  -->
    <property name="address" ref="address"/>
</bean>

<!--  3、array[]数组注入  -->
<bean id="user2" class="com.vxzx.pojo.User">
    <property name="hobbis">
        <array>
            <value>打球</value>
            <value>听歌</value>
        </array>
    </property>
</bean>

<!-- 4、List<>注入   -->
<bean id="user3" class="com.vxzx.pojo.User">
    <property name="likes">
        <list>
            <value>list1</value>
            <value>list2</value>
            <value>list3</value>
        </list>
    </property>
</bean>

<!-- 5、Map<>注入  -->
<bean id="user4" class="com.vxzx.pojo.User">
    <property name="cid">
        <map>
            <entry key="1" value="张三"/>
            <entry key="2" value="李四"/>
            <entry key="3" value="王五"/>
        </map>
    </property>
</bean>

<!-- 6、set注入  -->
<bean id="user5" class="com.vxzx.pojo.User">
    <property name="setcontext">
        <set>
            <value>set1</value>
            <value>set2</value>
            <value>set3</value>
        </set>
    </property>
</bean>

<!--  7、properties注入 -->
<bean id="user6" class="com.vxzx.pojo.User">
    <property name="por">
        <props>
            <prop key="username">vxzx</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>

3.3 扩展方式注入

扩展方式注入一共有两种:p-namespace和c-namespace

使用该扩展首先要先导入:

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

p-namespace的具体使用:p-namespace 允许您使用bean元素的属性(而不是嵌套的<property/>元素)来描述协作 Bean 的属性值,或同时使用这两者。

<!--  扩展c:namespace和p:namespace  -->
    <bean id="user8" class="com.vxzx.pojo.User" p:name="lin" p:age="11"/>

c-namespace的具体使用:c:命名空间执行,基于构造函数的依赖注入

    <bean id="user9" class="com.vxzx.pojo.User" c:name="lzx"/>

4、Bean自动装配

4.1 bean的作用域

创建 bean 定义时,将创建一个配方来创建该 bean 定义所定义的类的实际实例。默认状态下是单例模式。

Scope Description
singleton (默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype 将单个 bean 定义的作用域限定为任意数量的对象实例。
request 将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session 将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application 将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket 将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
  • singleton(单例)

仅 Management 一个 singleton bean 的一个共享实例,并且所有对具有 ID 或与该 bean 定义相匹配的 ID 的 bean 的请求都会导致该特定的 bean 实例由 Spring 容器返回。

<bean id="user" class="com.vxzx.pojo.User" scope="singleton"/>
User user = context.getBean("user", User.class);
User user2 = context.getBean("user", User.class);
System.out.println(user==user2);			//输出为true
  • prototype(原型)

每次对特定 bean 提出请求时,bean 部署的非单一原型范围都会导致创建一个新 bean 实例。

   <bean id="user" class="com.vxzx.pojo.User" scope="prototype"/>
User user = context.getBean("user", User.class);
User user2 = context.getBean("user", User.class);
System.out.println(user==user2);			//输出为false

4.2 自动装配

Spring 会在上下文自动寻找,并自动给bean装配属性。

一般来说有三种装配方式:

  • 在xml中显示的配置
    <bean id="user" class="com.vxzx.pojo.User">
        <property name="name" value="lin"/>
    </bean>
  • 在java中显示配置(JavaConfig)

  • 隐式自动装配bean

autowire="byName":寻找和自己对象set方法后面的值对应的beanid

<bean id="cat" class="com.vxzx.pojo.Cat"/>   

<bean id="user" class="com.vxzx.pojo.User" autowire="byName"/>

autowire="byType":寻找和自己对象属性相同的bean(class)

<bean id="cat" class="com.vxzx.pojo.Cat"/>   

<bean id="user" class="com.vxzx.pojo.User" autowire="byType"/>

总结:

byName:保证bean的id唯一,bean需要和注入的属性的set的值一致。

byType:保证bean的class唯一,需要和注入的属性的类型一致。

5、使用注解自动装配

与往常一样,您可以将它们注册为单独的 bean 定义,但是需要记得加上<context:annotation-config/>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
    <bean id="user" class="com.vxzx.pojo.User"/>
    <bean id="fish" class="com.vxzx.pojo.Fish"/>

</beans>

<context:annotation-config/>仅在定义它的相同应用程序上下文中查找 bean 上的注解。

5.1 使用@Autowired

@Autowired注解 应用于构造函数或者setter方法。

//方式一:
    @Autowired
	private Fish fish;
//方式二:
@Autowired
    public void setFish(Fish fish) {
        this.fish = fish;
    }

使用Autowired还可以自定义bean对应的id 的值。使用@Qualifier(value = "")

	@Autowired
	@Qualifier(value = "yu")
	private Fish fish;
<bean id="yu" class="com.vxzx.pojo.Fish"/>

使用@Autowired注解的时候,该对应的bean的值必须的存在的,不能为空,不然会报错。当然,如果想解决这种问题,我们可以使用required

  • required的值为true,则表示需要该bean的值不为空。
  • required的值为false,则表示允许该bean的值为空。
    @Autowired(required = false)
    private Bird bird;

使用@Nullable,说明这个字段可以为null;

5.2 使用@Resource

使用@Resourcejava注解实现自动装配:该注解为java的注解,而不是spring 的注解。

 @Resource
    private Mouse mouse;
<bean id="mouse" class="com.vxzx.pojo.Mouse"/>

@Resource的使用与@Autowired基本差不多,均可标注在字段或属性的setter方法上,但还是有一些区别的。

@Resource@Autowired的区别:

  • @Resource是spring中提供的注解,@Autowired是java中的提供的注解。

  • @Autowired默认使用byType方式自动装配,如果byType方式识别不了,则会使用byName方式。

简单来说就是:先byType,再byName

  • @Resource默认使用byName方式自动装配,如果byName方式识别不了,则会使用byType方式。

简单来说就是:先byName,再byType

6、使用注解开发

在Spring中,如果想要使用注解开发,必须先导入AOP包,不然无法使用。

SSM---Spring

SSM---Spring

开启注解扫描包:

		<!--  开启注解扫描包:  -->
        <context:component-scan base-package="com.vxzx.pojo"/>
        <context:annotation-config/>

@Compoent:放在类上,说明这个类被Spring管理了,相当于bean。

<bean id="" class=""></bean>
@Component
public class User {
    private String name;
}

@Value:放在属性上,可以给该属性赋值,相当于bean中的property。

 <property name="" value=""/>
    @Value("vx")
    private String name;

@Scope:放在类上,可以给这个类设置bean 的作用域。相当于bean中的scope。

<bean scope="singleton"/>
@Scope("singleton")
public class User {
}

@Compoent的几个衍生注解:

  • dao层的:@repository
  • server层的:@services
  • controller层的:@controller

其本质都与@Component一样,只是不同包下的注解名字不同。

6.1 扩展-Java Config

Spring提出的强大的JavaConfig这种类型安全的Bean装配方式,它基于Java代码的灵活性,使得装配的过程也变得及其灵活。即使用java的方式配置spring。使用JavaConfig方式则不需要使用XML配置。

1.@Configuration

  • 定义JavaConfig类时,都会在其上加注@Configuration注解,来表明这是一个配置类,@Configuration注解底层是@Component注解。
  • 引用时,这个注解会被AnnotationConfigApplicationContext来进行加载,AnnotationConfigApplicationContext是ApplicationContext的一个具体实现,代表依据配置注解启动应用上下文。
@Configuration
public class Myconfig {
    public User getuser(){
        return new User();
    }
}

以上配置等同于之前配置的一个application.xml文件。

还可以加上@ComponentScan组件扫描;

@Configuration
@ComponentScan(basePackages = "com.vxzx.pojo")
public class Myconfig {
    @Bean
    public User getuser(){
        return new User();
    }
}

表示该配置类,扫描了pojo包下的所有类。

2. @Bean

使用@Bean注解我们可以实现XML配置中手动配置第三方Bean的功能,这里我们使用方法来定义Bean,并在方法前面加注@Bean注解,表示要将该方法返回的对象加载到Spring容器中。

@Bean是方法级 注解,是 XML <bean/>元素的直接类似物。注解 支持<bean/>提供的某些属性。

@Configuration
public class Myconfig {
    @Bean
    public User getUser(){
        return new User();
    }
}

加上@bean相当于:

<bean id="getUser" class="com.acme.services.User"/>

3. @Import

使用@import注解可以将其他的类,注解导入到该配置类中来,整合成一个类。@Import注解 允许从另一个配置类中加载@Bean定义

@Configuration
@ComponentScan(basePackages = "com.vxzx.pojo")
@Import(People.class)
public class Myconfig {
    @Bean
    public User getuser(){
        return new User();
    }
}

即上文中将另外一个类People注入到该配置类中,与User类整合在一起。

4. 具体实现

与实例化ClassPathXmlApplicationContext时将 Spring XML 文件用作 Importing 的方式几乎相同,实例化AnnotationConfigApplicationContext时可以将@Configuration类用作 Importing。

如果使用@Configuration类作为 Importing ,则可以使用 AnnotationConfigApplicationContext 实例化 Spring 容器;

当提供@Configuration类作为 Importing 时,@Configuration类本身被注册为 bean 定义,并且该类中所有已声明的@Bean方法也被注册为 bean 定义。

public void test01(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class);
    User getuser = (User) context.getBean("getuser");
    System.out.println(getuser.getName());
}

7、代理模式

代理模式:为其他对象提供一种代理以控制这个对象的访问。

7.1 静态代理模式

静态代理是由程序或特定工具自动生成的源代码,在程序运行时,.class文件就已经存在了。

实体类:

public interface Renti {
    void rent();
}
public class Rent implements Renti{
    public void rent() {
        System.out.println("buy house!----真实对象");
    }
}

代理类:

public class RentProxy implements Renti{
    private Rent rent;

    public RentProxy(Rent rent) {
        this.rent = rent;
    }

    public void rent() {
        System.out.println("fiex!-----代理对象");
        rent.rent();
    }
}

测试类:

//静态代理模式:
@Test
public static void main(String[] args) {
    Rent rent = new Rent();
    RentProxy rentproxy = new RentProxy(rent);
    rentproxy.rent();
}

7.2 动态代理模式

动态代理指在运行时自动生成的代理类。

动态代理需要实现InvocationHandler接口的invoke方法:

  • 创建方法,必须调用Proxy类的静态方法newProxyInstance,该方法如下:

    Object Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws IllegalArgumentException

    • loder:表示类加载器,通过getClassLoader()获取
    • interfaces:表示需要代理的类的接口,通过getInterfaces获取
    • handler:表示调用处理器,实现了InvocationHandler接口的对象
  • 最后,在重载的invoke方法中,使用method.invoke()方法传参

实体类:

public interface Rent {
    void rent();
}
public class RentRel implements Rent{
    public void rent() {
        System.out.println("buy house!---真实主体!");
    }
}

代理类:

public class Proxydy implements InvocationHandler {
    //被代理的接口。
    private Object object = null;

    //生成得到的代理类。
    public Object newReal(Object real){
        this.object = real;
        Class<?> realClass = real.getClass();
        Object proxyInstance = Proxy.newProxyInstance(realClass.getClassLoader(),realClass.getInterfaces(),this);
        return proxyInstance;
    }

    //处理代理实例,并返回结果。
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理!!!!");
        //本质:使用反射机制实现动态代理。
        Object invoke = method.invoke(object, args);
        return invoke;
    }
}

测设类:

//动态代理模式:
public static void main(String[] args) {
    com.vxzx.dynamicproxy.Rent real = (com.vxzx.dynamicproxy.Rent) new Proxydy().newReal(new RentRel());
    real.rent();
}

8、AOP

8.1 简介

AOP英文名为Aspect Oriented Programming,意为面向切面编程,通过预编译方式和运行期间动态代理实现程序功能统一维护的一种技术。可以在其 前后加入 需要添加的东西。即在不改变代码的情况下,增加新的功能。

AOP中名词的解释:

  • JoinPoint(连接点):目标对象中,所有可以增强的方法,即Spring中允许你通知的地方,且只支持方法增强
  • aspect(切面):横切关注点,被模块化的特殊对象,即一个类
  • Advice(通知/增强):增强方法的代码、功能,即一个方法
    • 具体方法:Before、After、Around、AfterRunning、AfterThrowing
  • Pointcut(切入点):已确定增强的地方的定位点。
  • Target(目标对象):被代理的对象、被通知的对象、被增强的对象
  • Proxy(代理):将通知连接到目标对象之后形成的代理对象

8.2 AOP的具体实现

8.2.1 使用原生的Spring API实现

目标对象类:

public interface UserServer {
    public void add();
}
public class UserServerImp implements UserServer {
    public void add() {
        System.out.println("添加用户!");
    }
}

增强类:before

public class Before implements MethodBeforeAdvice {

    //method:要执行的目标对象的方法
    //objects(args):参数
    //o(target):目标对象
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("执行了" + o.getClass() + "的" + method.getName() + "方法");
    }
}

增强类:before

public class After implements AfterReturningAdvice {

    //o(returnValue):返回值;
    //其他的与before一样。
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了" + o1.getClass() + "的" + method.getName() + "方法" + "返回值:" + o);
    }
}

配置类:

<!--  注册bean  -->
	<bean id="user" class="com.vxzx.server.UserServerImp"/>
    <bean id="before" class="com.vxzx.server.Before"/>
    <bean id="after" class="com.vxzx.server.After"/>

<!--  配置AOP  -->
    <aop:config>
<!--   切入点;  execution表达式:execution(修饰词 类名.方法名.参数 )  -->
        <aop:pointcut id="point" expression="execution(* com.vxzx.server.UserServerImp.*(..))"/>
<!--   执行环绕增强:     -->
        <!--  把before类切入到point中去    -->
        <aop:advisor advice-ref="before" pointcut-ref="point"/>
        <aop:advisor advice-ref="after" pointcut-ref="point"/>
    </aop:config>

测试类:

        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserServer user = (UserServer) context.getBean("user");
        user.delete();

8.2.2 使用自定义方(切面定义)法实现

自定义增强方法:

public class Aopasp {
    public void b(){
        System.out.println("前置增强");
    }

    public void a(){
        System.out.println("后置增强");
    }
}

配置类:

    <bean id="asp" class="com.vxzx.server.Aopasp"/>
    <aop:config>
<!--切入点:-->
        <aop:pointcut id="pointcut" expression="execution(* com.vxzx.server.UserServerImp.*(..))"/>
<!--使用切面aspect方法: ref 需要引用的类 -->
        <aop:aspect ref="asp">
<!--前置增强:-->
            <aop:before method="b" pointcut-ref="pointcut"/>
<!--后置增强: -->
            <aop:after method="a" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

测试类:

     ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
     UserServer user = (UserServer) context.getBean("user");
     user.delete();

8.2.3 使用注解实现

注解实现类:

//表示该类是一个通知类(切面):
@Aspect
public class proxyanno {
    //设置切入点:
    @Pointcut("execution(* com.vxzx.serveranno.UserServerImp.*(..))")
    public void pc(){}

    @Before("proxyanno.pc()")
//    @Before("execution(* com.vxzx.serveranno.UserServerImp.*(..))")  指定前置增强,并且指定切入点
    public void before(){
        System.out.println("注解---前置增强");
    }

    @After("proxyanno.pc()")
//    @After("execution(* com.vxzx.serveranno.UserServerImp.*(..))")  指定后置增强,并且指定切入点
    public void after(){
        System.out.println("注解---后置增强");
    }

    @Around("proxyanno.pc()")
    public void around(ProceedingJoinPoint pj) throws Throwable {
        System.out.println("环绕增强--前");
        pj.proceed();
        System.out.println("环绕增强--后");
    }
}

配置类:

    <bean id="proxyanno" class="com.vxzx.serveranno.proxyanno"/>
<!--  开启注解实现AOP:  -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

测试类:

        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserServer user = context.getBean("user", UserServer.class);
        user.add();

9、整合Mybatis

9.1 Mybatis

需要导入的jar包:

SSM---Spring

整合Mybatis,数据源和sqlSessionFactory都可以在spring.xml中创建,即Mybatis中的所有配置都可以在Spring.xml中配置了,不在需要单独创建一个Mybatis.xml来创建数据源和sqlSessionFactory等信息。

配置一个为spring.xml的文件:

  • 创建DataSource(数据源):需要导入:org.springframework.jdbc包下的DriverManagerDataSource
<bean id="DataSource" class="org.springframework.jdbc.datasource.DriverMangerDataSource">
	<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=ture&apm;characterEncoding=utf-8"></property>
    <property name="username" value="root"></property>
    <property name="password" value="123456"></property>
</bean>
  • 创建sqlSessionFactory:需要导入:org.mybatis.spring包下的SqlSessionFactoryBean
<bean id="sqlSessionFactory" class="org.mybaits.spring.SqlSessionFactoryBean">
	<property name="Datasource" ref="DataSource"></property>
    <!--  绑定mybatis配置文件:-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:com/vxzx/mapper/*.xml"/>
</bean>
  • 创建SqlSessionTemplate,即我们使用的sqlsession,且只能使用构造器注入数据
<bean id="sqlsession" class="org.mybatis.spring.SqlSessionTemplate">
	<constructot-arg index="0" ref="sqlSessionFactory"></constructot-arg>
</bean>
  • 最后将实现类注入到配置的xml中
<bean id="usermapperimp" class="com.vxzx.mapper.userMapperImp">
	<property name="sqlSession" ref="sqlsession"></property>
</bean>

实体类:需生成GET、SET方法

public class User {
    private int id;
    private  String name;
    private  String pwd;
}

接口类:

public interface UserMapper {
    public List<User> selectu();
}

userMapper.xml:

<?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.vxzx.mapper.UserMapper">
		<select id="selectu" resultType="user">
        	select * from user;
        </select>
    </mapper>

具体实现类:UserMapperImp,使用到了SqlSessionTemplate;SqlSessionTemplate=sqlSession

public class UserMapperImp implements UserMapper {
    private SqlSessionTemplate sqlsession;

    public void setSqlsession(SqlSessionTemplate sqlsession) {
        this.sqlsession = sqlsession;
    }
	 public List<User> selectu() {
       UserMapper mapper = sqlsession.getMapper(UserMapper.class);
       return mapper.selectu();
    }
}

测试类:

@Test
public void test01(){
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    UserMapper mapper = context.getBean("usermapperimp",UserMapper.class);
    List<User> selectu = mapper.selectu();
    for (User user:selectu){
        System.out.println(user);
    }
}

9.2 拓展

利用实现类继承SqlSessionDaoSupport,来自动生成sqlSessionTemplate。

实现类:

public class UserMapperImp2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectu() {
        SqlSession session = getSqlSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        return mapper.selectu();
    }
}

配置类XML:

<!--  继承SqlSessionDaoSupport类,实现sqlSessionTemplate  -->
    <bean id="userMapper2" class="com.vxzx.mapper.UserMapperImp2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>

测试类:

    @Test
    public void mbtest02(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper mapper = context.getBean("userMapper2", UserMapper.class);
        for (User user : mapper.selectu()) {
            System.out.println(user);
        }
    }

总结:1、创建生成数据源

​ 2、创建sqlSessionFactory

​ 3、创建sqlSessionTemplate

​ 4、创建具体实现类

​ 5、将具体实现类注入到Spring中

10、声明式事务

Spring中propagation的七种事务配置

事务属性 详解
REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务。
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED 支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

事务的重要性

  • 如果不配置事务,就会存在数据提交不一致的问题。
  • 如果不在Spring中配置,则需要在代码中手动配置事务。

在Spring中配置事务:

<!--  设置声明式事务: 需要创建一个 DataSourceTransactionManager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="DataSource"/>
    </bean>

<!--  结合AOP是实现事务的织入  -->
    <tx:advice id="traDriver" transaction-manager="transactionManager">
<!--   propagation :设置传播方式!    -->
        <tx:attributes>
<!--            <tx:method name="add" propagation="REQUIRED"/>-->
<!--            <tx:method name="delete" propagation="REQUIRED"/>-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

<!--  配置AOP切面,将事务切入到需要实现事务的实例中去:  -->
    <aop:config>
        <aop:pointcut id="driverPoint" expression="execution(* com.vxzx.mapper.*.*(..))"/>
        <aop:advisor advice-ref="traDriver" pointcut-ref="driverPoint"/>
    </aop:config>

总结:如果遇到sql语句中有错误,但是却执行成功,则需要配置事务;

  • 在Spring中,需要先设置声明事务,创建一个DataSourceTransactionManager
  • 结合AOP织入事务,<tx:advice />
  • 最后需要设置AOP将我们设置好的事务横切入需要事务的实例中
上一篇:SSM框架学习笔记之SpringMVC异常处理机制


下一篇:org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()Ljava/lang/Integer;