spring

Spring概念

1.是轻量级的开源的javaee框架。

2.解决企业应用开发的复杂性。

3.核心部分 IOC和AOP

(1)IOC:控制反转,把创建对象过程交给spring进行管理。

(2)AOP:面向切面,不修改源码进行功能增强。

4.特点

(1)方便解耦,简化开发。

(2)AOP编程

(3)方便程序的检测

(4)方便和其他框架进行整合

(5)降低javaee API的使用难度

(6)方便进行事务操作

演示案例

(1)下载spring

(2)idear创建新项目

(3)导入spring5 相关jar包

Beans、Core、Contert、Expression、commons

idear中新建文件夹lib,jar包复制到lib中,将jar包导入项目中

peoject structure -> Modules -> "+" 选择5个jar包

(4)创建普通类,在这个类创建普通方法

创建包com.xqn.spring5, 创建类User,并删除自带main

public class User {
    public void add () {
        system.out.println("add.......");    
    }

}

(5)创建对象

创建对象有两种方式:配置文件和注解。本次用配置文件。

创建spring配置文件,在配置文件配置创建的对象。

spring配置文件用xml格式(resource Bundle)

<bean id ="user" class = "com.xqn.spring5.User"></bean>

id:取的名字

class:写全路径

bean:专门创建对象

(6)进行测试代码编写

只在测试时用,实际应用中不写,而是通过web层调用。

创建testdome包,TestSpring5类,引入Test包

public class TestSpring5{
    @Test
    public void testAdd(){
        //1.加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("类路径");
        //2.获取配置创建的对象
        User user = context.getBean ('user',User.class);//转换类型
        System.out.println(user);
        user.add();
    }
}

IOC容器

什么是IOC

控制反转,通过控制反转,把对象创建和对象之间的调用过程(一个类调用另一个类的方法),交给spring进行管理。

目的是降低代码之间的耦合度。

IOC底层原理

xml解析、工厂模式、反射

原始方法

创建对象调用

耦合度太高了

优化方案:工厂模式

目的:耦合度降低到最低限度

IOC过程

第一步 xml配置文件,配置创建对象

第二步 创建工厂类

IOC(接口)

1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2.spring提供IOC容器实现两种方式:(两个接口)

BeanFactory:IOC容器基本实现,spring内部使用接口,不提供开发人员进行使用。加载配置文件时不会创建对象在获取对象(使用)才去创建对象(很像懒汉式)

ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。加载配置文件时就会创建对象。

常用第二种,(加载时间长一些)服务器启动时加载,耗时耗资源的过程交给服务器。

3.ApplicationContext接口有实现类

两个主要实现类:

FileSystemXmlApplicationContext  全路径

ClassPathXmlApplicationContext   类路径

IOC操作Bean管理

什么是Bean

指的是两个操作:创建对象和注入属性

Bean管理操作有两种方式:基于xml配置文件方式实现和基于注解方式实现。

基于xml方式

基于xml方式创建对象

1.在spring配置文件中,使用bean标签,标签里添加对应属性,就可以实现对象的创建。

2.在bean标签有很多属性,介绍常用的属性:

        id:唯一标识

        class:类全路径(包类路径)

3.创建对象时,默认执行无参构造方法

基于xml方式注入属性

DI:依赖注入,注入属性,是IOC中一种具体实现,在创建对象基础之上。

第一种注入方式:使用set方法

类里面要有set方法

<bean id = "..." class = "...">
    <property name ="属性名" value = "值"> </property>
    <property name ="属性名" value = "值"> </property>
</bean>
第二种注入方法:有参构造注入
<bean id = "..." class = "...">
    <constructor-arg name ="属性名" value = "值"> </constructor-arg>
</bean>

或者使用属性索引

<bean id = "..." class = "...">
    <constructor-arg index ="属性索引" value = "值"> </constructor-arg>
</bean>
简化set方法注入(属性连续注入)

1.添加p名称空间在配置文件中

2.进行属性注入,在bean标签里面进行操作

<bean id = "..." class = "..." p:属性1名 = "值" p:属性2名 = "值">
</bean>
注入其他类型属性
字面量类型

字面量:设置属性固定值

1.null

<property name = "属性名">
    <null/>
</property>

2.属性包含特殊符号

(1)转义 使用&lt和&gt

(2)把带特殊符号内容写到CDATA中

<property name = "属性名">
    <value> <![CDATA[《三国》]]> </value>
</property>
class类型

创建两个类service和继承dao接口的类

在service调用dao里面的方法

在spring配置文件中配置

1.外部bean

外部创建对象然后ref引用

<bean id = "userService" class = "...">
    <property name ="userDao" ref = "userDaoImpl"> </property>
</bean>
<bean id = "userDaoImpl" class = "...">
</bean>

2.内部bean

<bean id = "userService" class = "...">
    <property name ="userDao" >
        <bean id = "userDaoImpl" class = "..."> </bean>
            <property name = "" value = ""> </property>
    </property>
</bean>

3.级联赋值

(1)一对多关系:部门和员工

一个部门有多个员工,一个员工属于一个部门

创建Dept 部门类和Emp 员工类

第一种

<bean id = "emp" class = "...">
    <property name ="属性名" value = "值"> </property>
    <property name ="dept" ref = "dept"> </property>
</bean>
<bean id = "dept" class = "...">
    <property name ="属性名" value = "值"> </property>
</bean>

第二种

需要在Emp中生成get方法

<bean id = "emp" class = "...">
    <property name ="属性名" value = "值"> </property>
    <property name ="dept" ref = "dept"> </property>
</bean>
<bean id = "dept" class = "...">
    <property name ="dept.属性名" value = "值"> </property>
</bean>
集合类型

1.注入数组类型属性

2.注入List类型

3.注入Map类型

4.注入set类型

第一步 创建类,定义数组、list、map、set类型属性,生成对应的set方法

第二步 在spring配置文件进行配置

<bean id = "stu" class = " ">
    <!--注入数组类型,<list><array>都支持String数组-->
    <property name = "coursers">
        <array>
            <value> 值 </value>
            <value> 值 </value>
        </array>
    </property>
    <!--注入list类型-->
    <property name = "list">
        <list>
            <value> 值 </value>
            <value> 值 </value>   
        </list>
    </property>
    <!--注入map类型-->
    <property name = "maps">
        <map>
            <entry key = "键" value = "值"> </entry>
            <entry key = "键" value = "值"> </entry>
        </map>
    </property>
    <!--注入set类型-->
    <property name = "sets">
        <set>
            <value> 值 </value>
            <value> 值 </value>   
        </set>
    </property>
</bean>

5.在集合里面设置对象类型值

<bean id = "course" class = "...">
    <property name ="courselist">
        <list>
            <ref bean = "course1"> </ref>
            <ref bean = "course2"> </ref>
        </list>
    </property>
</bean>
<bean id = "course1" class = "...">
    <property name ="属性名" value = "值"> </property>
</bean>
<bean id = "course2" class = "...">
    <property name ="属性名" value = "值"> </property>
</bean>

6.把集合注入部分提取出来

第一步 在spring配置文件中引入名称空间util

第二步 使用util标签完成list集合注入提取

<util:list id = "bookList">
    <value> 值 </value>
    ...
</util:list>
<bean id = "book" class = " ">
    <property name = "list" ref = "bookList">
    </property>
</bean>

FactoryBean(内置bean)

1.spring有两种类型bean,一种是普通bean,另一种是工厂bean

2.普通bean:class = 定义什么类型,返回什么类型,在配置文件中定义bean类型就是返回类型

3.工厂bean:返回类型可以和在配置文件定义bean类型不一样

        第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean

        第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

bean的作用域

1.在spring里面,设置bean创建单实例还是多实例

2.在spring里面,默认情况下,bean是单实例对象

3.如何设置单实例还是多实例

(1)在spring配置文件bean标签里面有属性(scope)用于设置单属性还是多属性

(2)scope属性值:

        第一个值 singleton,默认值,表示单实例对象。

        第二个值 prototype,表示多实例对象。

<bean id = "" class = "" scope = "prototype或者singleton">
...
</bean>

(3)singleton 和 prototype的区别

a).singleton是单实例    prototype是多实例

b).设置scope值是singleton时,加载spring配置文件时会创建单实例对象

c).设置scope值是prototype时,不是在加载spring配置文件时会创建,而是在调用getBean方法           时,创建多实例对象

bean生命周期

从对象创建到对象销毁的过程

1.通过构造器创建bean实例(无参构造)

2.为bean的属性设置值和对其他bean的引用(调用set方法)

3.调用bean的初始化方法(需要进行配置)

4.bean可以使用了(对象获取到了)

5.当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)

bean的后置处理器,bean生命周期有七步

创建类,实现接口BeanPostProcessor,创建后置处理器,重写postProcessBeforeInitialization(Object, String)和postProcessAfterInitialization(Object, String)需要在配置文件中配置

1.通过构造器创建bean实例(无参构造)

2.为bean的属性设置值和对其他bean的引用(调用set方法)

3.把bean实例传递bean后置处理器的方法postProcessBeforeInitialization(Object, String)

4..调用bean的初始化方法(需要进行配置)

5.把bean实例传递bean后置处理器的方法postProcessAfterInitialization(Object, String)

6.bean可以使用了(对象获取到了)

7.当容器关闭时,调用bean的销毁方法(需要进行配置销毁的方法)

xml自动装配

手动装配:通过property标签手动设置name和value

1.根据指定装配规则(属性名称或者属性类型)spring自动将匹配的属性值进行注入

2.bean标签属性autowire配置自动装配,autowire属性常用两个值:

        byName根据属性名称注入

        byType根据属性类型注入

<bean id = "" class = "" autowire = "byName或者byType"
...
</bean>

引入外部属性文件

1.直接配置数据库信息

(1)引入德鲁伊连接池依赖的jar包(复制,导入)

(2)配置德鲁伊连接池

配置文件:

<bean id = "dateSource" class = "com.alibaba.druid.pool.DruidDataSource">
    <property name = "driverClassName" value = "com.mysql.jdbc.Driver"></property><!--驱动名称-->
    <property name = "url" value = "————"></property><!--数据库地址-->
    <property name = "username" value = "root"></property><!--数据库用户-->
    <property name = "password" value = "root"></property><!--数据库密码-->
</bean>

2.引入外部属性文件配置数据库连接池

(1)创建外部属性文件,properties格式文件,写数据信息

prop.driverClass = com.mysql.jbdc.Driver

prop.url = 

prop.userName = 

prop.password =

“=”左边可以随便写,建议不只写一个单词,容易冲突。

(2)把外部properties属性文件引入到spring配置文件中

引入context名称空间

在spring配置文件使用标签引入外部属性文件

<!--引入外部属性文件-->
<context:property-placeHolder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id = "dateSource" class = "com.alibaba.druid.pool.DruidDataSource">
    <property name = "driverClassName" value = "${prop.driverClass}"></property><!--驱动名称-->
    <property name = "url" value = "${prop.url}"></property><!--数据库地址-->
    <property name = "username" value = "${prop.userName}t"></property><!--数据库用户-->
    <property name = "password" value = "${prop.password}"></property><!--数据库密码-->
</bean>

基于注解方式

什么是注解

1.注解是代码特殊标记格式:@注解名称(属性名称=属性值,...)

2.注解作用在类上面、方法上面、属性上面

3.使用注解目的:简化xml配置

创建对象4个注解

1.@Component  一般用于普通注解

2.@Service  一般用于业务逻辑层,service层

3.@Controller  一般用于web层

4.@Repository  一般用于到层(持久层)

上面4个注解功能是一样的,都可以用来创建bean实例

基于注解实现对象创建

第一步 引入依赖  spring-aop-....RELEASE.jar

第二步 开启组件扫描,配置文件context

<context:component-scan base_package="">
</context:component-scan>

如果扫描多个包

方法一:使用逗号隔开

方法二:扫描包上层目录

第三步 创建类,在类上面添加创建对象注解

@Component (value = "userService")
public class UserService{
    public void add(){
    ...
    }
}

在注解里面value属性值可以省略不写,默认值是类名称,首字母小写

注意:

<context:component-scan base_package="——————"
    use-default-filters = "false">
    <context:include-filter                     <!--设置扫描哪些内容-->
               type = "annotation"              <!--根据注解扫描--> 
               expression = "org.springframework.stereotype.Controller"/>     
                                                <!--表达式,只扫描Controller注解-->   
</context:component-scan>

context:exclude-filter :设置哪些内容不进行扫描

use-default-filters = "false"表示现在不使用默认filter(全部扫描),自己配置filter。

context:include-filter 设置扫描哪些内容

type = "annotation" 根据注解扫描

expression = "org.springframework.stereotype.Controller" 表达式,只扫描Controller注解

context:exclude-filter :设置哪些内容不进行扫描

基于注解实现属性注入

1.@Autowired               根据属性类型进行自动装配

2.@Qualifier                  根据属性名称进行注入

3.@Resource                可以根据类型注入,也可以根据名称注入

4.@Value                        注入普通类型属性

演示:

第一步 把service和dao对象创建,在service和dao类添加创建对象注解

第二步 在service注入dao对象,在service类添加dao类型属性,在属性上面使用(Autowired)注解(不需要添加set方法)

@Qualitier:根据属性名称进行注入,需要和@Autowired一起使用

完全注解开发

1.创建配置类,替代xml配置文件

@Configuration
@ComponentScan(basePackages={"包路径"})//相当于开启扫描
public class SpringConfig{
...
}

2.编写测试类

public void testService(){
    ApplicationContext context = new AnnotainConfigApplicationContext(SpringConfig.class);//加载配置类
}

AOP

什么是AOP

面向切面编程(方面)

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

通俗描述:不通过修改源代码方式,在主干功能里面添加新功能。

AOP底层原理

AOP底层使用动态代理

两种情况的动态代理

有接口

使用jdk动态代理

        创建接口实现类代理对象,增强类的方法。

1.使用jdk动态代理,使用Proxy(java.long包)类里面的方法创建代理对象

static object   newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)

返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。

第一个参数:类加载器

第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口。

第三个参数:实现这个接口InvocationHandler的类,创建代理对象,写增强方法。

2.编写JDK动态代理代码

(1)创建接口,实现方法

public interface UserDao{
    public int add (int a , int b);
    public int update(String id);
}

(2)创建接口实现类,实现方法

public class UserDaoImpl implements UserDao{
    public int add(int a , int b) {
        return a+b;
    }
    public String update(String id) {
    return id;
    }
}

(3)使用Proxy类创建接口代理对象

public calss JDKProxy{
	public static void main(String[] args){
		//创建接口实现类代理对象
		Class[] interfaces = {UserDao.class};//此源代码只有一个接口,接口数组,第二个参数

		UserDaoImpl UserDao = new UserDaoImpl();

		UserDao dao =(UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(UserDao))
        dao.add(1,2);
	}


class UserDaoProxy implements InvocationHandle{
	//重写方法,需要传入之前方法(使用有参构造器传递之前类),再写新增方法,第三个参数
	private Object obj;
	public UserDaoProxy(Object, obj){
		this.obj = obj;
	}


	public Object invoke(Object Proxy, Method, Object[] args) throws Throwable {
		System.out.Println("方法之前执行。。。" + Method.getName() + "传递参数" +
Arrays.toString(args));
		Object res = Method.invoke(obj, args);
		System.out.Println("方法之后执行。。。" + obj;
			return res;
	}
}

没有接口

使用CGLIB动态代理。

        创建当前类子类的代理对象,增强类的方法。

AOP术语

1.连接点

类里面哪些方法可以被增强,这些方法称为连接点。

2.切入点

实际被真正增强的方法,称为切入点。

3.通知(增强)

实际增强的逻辑部分称为通知(增强)。

通知有多种类型:前置通知、后置通知、环绕通知、异常通知、最终通知

4.切面

是个动作,把通知应用到切入点过程。

AOP操作(准备)

1.spring框架一般基于AspectJ实现AOP操作。

 AspectJ不是spring组成部分,独立于AOP框架,一般把AspectJ和spring一起使用,进行AOP操作。

2.基于AspectJ实现AOP操作

(1)基于xml配置文件

(2)基于注解方式(常使用)

3.在项目工程里面引入AOP相关依赖

4.切入点表达式

(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强。

(2)语法结构

execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))

如:

对com.xqn.dao.BookDao类里面的add进行增强

execution(* com.xqn.dao.BookDao.add (..))

对com.xqn.dao.BookDao类里面的所有方法进行增强

execution(* com.xqn.dao.BookDao.* (..))

对com.xqn.dao.包里面的所有类,类里所有方法进行增强

execution(* com.xqn.dao.*.* (..))

基于注解方式对AspectJ操作

1.创建类,在类里面定义方法

public class User {
    public void add(){
        System.out.println("add.....");
    }
}

2.创建增强类

public class UserProxy {
    public void before(){
        System.out.println("before.....");
    }
}

3.进行通知的配置

(1)在spring配置文件中,开启注解扫描。

添加aop名称空间

开启注解扫描

<context: component-scan base-package = "包路径">
</context: component-scan>

(2)使用注解创建User和UserProxy对象

在被增强的类和增强类上面添加@Component

(3)在增强类上面添加注解@Aspect

(4)在spring配置文件中开启生成代理对象

<aop:aspectj-atuoproxy></aop:aspectj-atuoproxy>

4.配置不同类型的解

(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

public class UserProxy {
    //前置通知
    @Before(value = "execution(* com.xqn.dao.User.add (..))
    public void before(){
        System.out.println("before.....");
    }

    //后置通知,在方法返回结果之后执行,有异常不执行
    @AfterRrturning = "execution(* com.xqn.dao.User.add (..))
    public void afterRrturning(){
        System.out.println("AfterRrturning.....");
    }

    //最终通知,在方法执行之后执行,不管有没有异常都执行
    @After = "execution(* com.xqn.dao.User.add (..))
    public void after(){
        System.out.println("After.....");
    }
    
    //环绕通知
    @Around(value = "execution(* com.xqn.dao.User.add (..))
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("环绕之前.....");
        proceedingJoinPoint.proceed();//被增强的方法执行
        System.out.println("环绕之后.....");
    }

    //异常通知
    @AfterThrow(value = "")
}

5.相同切入点抽取

在增强的类中创建一个方法

@Pointcut(value= " ")

public void pointdemo(){

}

通知变为:@After(value = "Pointdemo()")

6.有多个增强类对同一个方法进行增强,设置增强类优先级

在增强类上面添加注解@Order(数字类型值)

数字类型值越小优先级越高

完全注解

创建配置类,不需要创建xml配置文件

@Configuration

@ComponentScan(basePackages={" 包路径"}//组件扫描

@EnableAspectJAutoProxy(proxyTargetClass = true)//生成对象

public class ConfigAop{

}

基于配置文件对AspectJ操作

1.创建两个类,增强类和被增强类,创建方法

public class Book{
    public void bug() {
        System.out.println(" bug....");
    }    
}
public class BookProxy{
    public void before() {
        System.out.println(" before....");
    }    
}

2.在spring配置文件中创建两个类对象

<!--创建对象-->
<bean id = "book" class = " "> </bean>
<bean id = "bookProxy" class = " "> </bean>


<!--配置aop增强-->
<aop:config>
    <!--切入点-->
    <aop:pointcut id = "p"
    expression="execution(  )"/>

    <!--配置切面-->
    <aop:aspect ref:"bookProxy">
    <!--增强作用在具体方法上-->
        <aop: before method = "before" pointcut-ref="p"/>
    </aop:aspect>
</aop:config>

3.在spring配置中配置

JdbcTemplate

什么是JdbcTemplate

Spring框架对JDBC进行封装,使用jdbcTemplate方便实现对数据库操作

准备工作

(1)引入相关jar包

(2)在spring配置文件配置数据库连接池

<bean id ="dataSource" class ="comalibaba.druid.pool.DruidDataSource" destory-method = "close">
    <property name ="url" value = "   "/>
    <property name ="username" value = "root"/>
    <property name = "password" value = "root"/>
    <property name = "driverClassName" value = "...."/>
</bean>

(3)配置jbdcTemplate对象,注入DataSource

<bean id ="JdbcTemplate" class ="...."></bean>
    <property name = "dataSource" ref = "dataSource"></property>
</bean>

(4)创建service,创建dao类,在dao注入jdbcTemplate对象

class BookService

@Service
public class BookService{

}

interface BookDao


public interface BookDao{

}

class BookDaoImpl

@Repository
public class BookDaoImpl implements BookDao{
}

(5)开启组件扫描

<context:component-scan base-package="  "></context:component-scan>

(6)注入属性

@Service
public class BookService{
    @Autowired
    private BookDao bookDao;
    public void addBook(Book book){
        bookDao.add(book);
    }

}
public interface BookDao{
 
}
@Repository
public class BookDaoImpl implements BookDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
   
}

jdbcTemplate操作数据库(添加)

1.对应数据库创建实体类

public class Book{
    private String userId;
    private String username;
    private String status;
    //再加上get和set方法
}

2.编写service和dao

(1)在dao进行数据库添加操作

public interface BookDao{
    public void add(Book book);

}
@Service
public class BookService{
    @Autowired
    private BookDao bookDao;
    public void addBook(Book book){
        bookDao.add(book);
    }

}

(2)调用jdbcTemplate对象里面update方法实现添加操作

update(String sql, Object ... args)用于增加修改和删除

有两个参数

第一个参数:sql语句

第二个参数:可变参数,设置sql语句值

@Repository
public class BookDaoImpl implements BookDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public void add(Book book){
        //1.创建sql语句
        String sql = "inset into t_book values(?,?,?)";
        //2.调用方法实现
        Object[] args ={book.getUserId(), book.getUsername(), book.getUserstatus()};
        int update = jdbcTemplate.update(sql, args);
        System.out.println(update);
    }
}

(3)测试类

public void testJdbcTemplate(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml";
    BookSource bookService = context.getBean("bookService", BookService.class);
    Book book = new Book();
    book.setUserId("1");
    book.setUsername("java");
    book.serUserstatus("a");
    bookService.addBook(book);
}

jdbcTemplate操作数据库(查询)

1.查询返回某个值

 调用jdbcTemplate对象里面queryForObject方法实现查询操作

queryForObject(String sql, Class<T>requiredType)

有两个参数

第一个参数:sql语句

第二个参数:返回类型class

@Repository
public class BookDaoImpl implements BookDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public int select(){
        //1.创建sql语句
        String sql = "select count(*) from t_book";
        //2.调用方法实现
        Interger count = jdbcTemplate.queryForObject(sql, Interger.class);
        return count;
    }
}

2.查询返回对象

 调用jdbcTemplate对象里面queryForObject方法实现查询对象操作

queryForObject(String sql, RowMapper<T> rowMapper, Object ...args)

有两个参数

第一个参数:sql语句

第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装。

第三个参数:sql语句值

public Book findBookInfo(String id){
    String sql = "select * from t_book where user_id = ?";
    Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>            (Book.class), id);
    return book;
}

3.查询返回集合

 调用jdbcTemplate对象里面query方法实现查询集合操作

query(String sql, RowMapper<T> rowMapper, Object ...args)

有两个参数

第一个参数:sql语句

第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装。

第三个参数:sql语句值

public Book findAllBook(){
    String sql = "select * from t_book where user_id = ?";
    List<Book> bookList = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>            (Book.class), id);
    return bookList;
}

批量操作

1.批量操作,操作表里面多条记录。

2.jdbcTemplate实现批量添加操作

batchUpdate(String sql, LIst<Object[]> batchArgs)

有两个参数

第一个参数:sql语句

第二个参数:List集合,添加多条记录数据。

public void batchAddBook(List<Object[]> batchArgs){
    //遍历添加
    String sql = "insert into t_book values(?,?,?)";
    //返回影响行数
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
    System.out.println(Array.toString(ints));
}

事务管理

什么是事务

(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败。

事务特性(ACID)

(1)原子性

要么都成功,要么都失败。

(2)一致性

操作之前与操作之后总量不变

(3)隔离性

多事务操作时,各事务之间不会产生影响

(4)持久性

提交后表中数据固定

事务操作例子(转账)

webservicedao
视图部分

业务操作

1.调用dao两个的方法

数据库操作

不写业务

创建两个方法

1.少钱的方法

2.多钱的方法

1.创建数据库表,添加记录

2.创建service搭建dao完成对象创建和注入关系

(1)service注入dao,在dao注入jdbcTemplate,在jdbcTemplate注入DataSource

3.dao创建两个方法,多钱和少钱的方法,在service创建方法(转账的方法)

事务操作过程

try{
    //第一步 开启事务
    //第二步 业务操作
    //第三步 没有发生异常,提交事务
} catch (Exception e) {
    //第四步 出现异常,事务回滚 
}

Spring事务管理介绍

1.事务添加到javaee三层结构里面service层(业务逻辑层)

2.在Spring进行事务管理操作

(1)有两种方式,编程式事务管理和声明式事务管理(常使用)

3.声明式事务管理

(1)基于注解方式

(2)基于xml配置文件方式

4.在spring进行声明式事务管理,底层使用AOP原理

5.Spring事务管理API

提供一个接口,代替事务管理器,这个接口针对不同的框架提供不同的实现类。

注解声明式事务管理

1.在spring配置文件配置事务管理器

<bean id = "transactionManager" class = "....">
    <!--注入数据源-->
    <property name = "dataSource" ref = "dataSource"> </property>
</bean>

2.在spring配置文件,开启事务注解

(1)在spring配置文件引入名称空间tx

(2)开启事务注解

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

3.在service类上面(或者service类里面方法上面)添加事务注解

(1)@Transactional这个注解添加到类上面,也可以添加方法上面

(2)如果把这个注解添加到类上面,这个类里面所有的都方法添加事务。

(3)如果把这个注解添加方法上面,为这个方法添加事务

声明式事务管理参数配置

1.propagation :事务传播行为

当一个事务方法被另一个事务方法调用的时候,这个事务方法如何进行。

REQUIRED(required):如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行。

REQUIRED_NEW(required_new):当前的方法必须启动新事物,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起。(分内外层,内外层互不相关,外层出现异常,内层依旧可以提交。)

SUPPORTS(supports):如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中。

2.ioslation:事务隔离级别

(1)事务有特性称为隔离性,多事务操作之间不会产生影响,不考虑隔离性会产生很多问题。

(2)有三个读问题:脏读、不可重复读、幻读

(3)脏读:一个未提交事务读取到另一个未提交事务的数据

(4)不可重复读:一个未提交事务读取到另一提交的修改数据

(5)幻读:一个未提交事务读取到另一提交事务的添加事务

通过设置事务隔离级别解决读问题。

脏读不可重复读幻读

READ UNCOMMITTED

read uncommited

(读未提交)

READ COMMITTED

read committed

(读已提交)

×

REPEATABLE READ

repeatable read

(可重复读)

××

SERIALIZABLE

serializable

(串行化)

×××

设置:@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)

3.timeOut:超时时间

(1)事务需要在一定时间内提交,如果不提交进行回滚。

(2)默认值是-1,设置时间以秒为单位进行计算。

4.readOnly:是否只读

(1)默认值false,值为true只能查询。

5.rollbackFor:回滚,出现哪些异常进行回滚

6.noRollbackFor: 出现哪些异常不进行事务回滚。

xml声明式管理事务

1.在spring配置文件中进行配置

第一步:配置事务管理器

<bean id = "transactionManager" class = "  ">
    <prooerty name = "dataSource" ref= "dataSource"></property>
</bean>

第二步:配置事务相关参数,通知

<tx:advice id = "txadvice">
    <!--配置事务参数-->
    <tx:attributes>        <!--指定哪种规则的方法上面添加事务-->   
        <tx:method name "accountMoney"/>
        <!--tx:method name "account*"/-->
    </tx:attributes>
</tx:advice>

第三步:配置切入点和切面

<aop:config>
     <!--切入点-->
    <aop:pointcut id = "pt" expression = "execution(....)"/>
    <!--配置切面-->
    <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>

完全注解声明式事务管理

@Configuration

@ComponentScan(basePackages=" ")//组件扫描

@EnableTransactionManagement//开启事务

public class TxConfig{
        //创建数据库连接池
        @Bean
        public DruidDataSource getDruidDataSource(){
            dataSource.setDriverClassName("  ");
            ....
        }


        //创建jdbc对象
        @Bean
        public JdbcTemplate (DataSource dataSource){//到ioc容器中根据类型找到dataSource
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            //注入DataSource
            jdbcTemplate.setDataSource(dataSource);
            return jdbcTemplate;
        }


        //事务管理器对象
        @Bean
        public DataSourceTransactionManager getDataSourceTransactionManager(DataSource datasource){
            DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
            transactionManager.setDataSource(dataSource);
            return transactionManager;
        }
}

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值