springAOP 学习

AOP(面向切面编程)

特点:不通过修改源代码的方式添加新功能(这个详细可以去百度)
1.AOP(底层原理)
AOP底层使用动态代理:一般有两种:
一种是有接口(使用JDK动态代理),另一种是没有接口(使用CGLIB动态代理)
有接口的我们是通过:创建接口实现类代理对象,增强方法
没有接口的我们是通过:创建代理类子类的代理对象,增强方法

JDK动态代理

1.使用JDK动态代理,使用proxy类里面方法创建代理类对象(newProxyInstance),这个方法返回指定接口的代理类的实列 ,该方法将方法调用分派给指定的调用处理程序

newProxyInstance(classLoader loader,类<?> interfaces,InvocationHandler h)
这个方法有三个参数
第一个参数:类加载器
第二个参数:增强方法所在类,这个类实现的接口,支持多个接口
第三个参数:这个参数是一个对象而这个对象需要去实现一个InvocationHandler接口,
InvocationHandler接口里面有一个invoke()方法
invoke(Object proxy, Method method, Object[] args)方法有三个参数:
第一个是:代理对象
第二个是:当前方法
第三个是:当前参数
method.invoke( 对象,参数);执行方法
我们先来测试一下 用法:
准备工作:
1.创建一个dao包在包中写Userdao.java接口和UserdaoImpl.java去实现这个接口
2.在创建一个proxy包在包中写JDKproxy.java实习(newProxyInstance)通过这个方法我们来增强UserdaoImpl.java类

在Userdao.java接口中写两个方法add()和zhi()两个方法

package com.xiaoran.spring.dao;

public interface Userdao {
    public int add(int a, int b);
    public String zhi(String t);

}

在UserdaoImpl.java中写

package com.xiaoran.spring.dao;

public class UserdaoImpl implements Userdao {
    public int add(int a, int b){
        return a+b;
    }
    public String zhi(String a){
        return a;
    }
}

创建JDKproxy.java在类中写

package com.xiaoran.spring.proxy;

import com.xiaoran.spring.dao.Userdao;
import com.xiaoran.spring.dao.UserdaoImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class JDKproxy {
    public static void main(String args[]) {
        //创建接口实现类代理对象
        Class[] interfac = {Userdao.class};
        UserdaoImpl userdao=new UserdaoImpl();
        Userdao userdao1=(Userdao) Proxy.newProxyInstance(JDKproxy.class.getClassLoader(), interfac, new invocationHandler(userdao));
        userdao1.add(1,2);
    }
}
class invocationHandler implements InvocationHandler {
    //把创建的是谁的代理对象,把谁传递过来
    //有参构造
    private Object obj;

    public invocationHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法之前执行:" + method.getName() + "传递的参数:" + Arrays.toString(args));
        Object res=method.invoke(obj,args);
        System.out.println("方法之后执行");
        return res;
    }

}

请添加图片描述
最后执行的结果为:
请添加图片描述

springAOP中的 术语

  1. 连接点:类里面哪些方法可以被增强,这些方法称为连接点。
  2. 切入点:实际被真正增强的方法,称为切入点
  3. 通知:实际增强的逻辑部分我们就称为通知
  4. 切面:把通知应用到切入点的过程

ASPectJ

spring框架中一般都是基于ASPectJ实现AOP操作
ASPectJ实现AOP操作:
1.基于xml配置文件实现
2.基于注解方式实现(使用多一些)

准被工作我们需要引入AOP依赖:直接把这个 lib包添加进去
切入点表达式::
语法结构:execution([权限修饰符][返回值类型][类全路径]方法名称

列子1:对com.xiaoran.spring.dao.BookDao 中的add增强

* 表示所有
execution(* com.xiaoran.spring.dao.BookDao.add(..))

Aop操作Aspect注解

1.创建一个类User.java
2,创建一个增强类Userproxy.java
(1)在增强类中创建方法,让不同的方法代表不同的通知类型
3.进行通知配置
(1)在spring.xml中开启注解扫描
(2)使用注解创建以上两个类
(3)在增强类上面添加注解@Aspect 这个注解的意思是:这个类生成一个你的代理对象
(4)在spring配置文件中开启生成代理对象
接下来我们就来实现一下:
1.我们新创建一个User.java在里面写一个add()方法,我们直接使用注解@component的方式创建对象
就不用在bean中写了

package com.xiaoran.spring.aspectAnno;

import org.springframework.stereotype.Component;

@Component
public class User{
    public void add(){
            System.out.println("add...。。方法执行");
        }
}

2.创建一个Userproxy.java在这里面写我们增强的方法,
用一个注解@component//创建对象
用一个注解@Aspect//开启代理生成对像
在增强类里面,在作为通知方法上面添加通知类注解,使用切入点表达式配置
通知类注解有5种:

  1. @Before 前置通知
  2. @After 在方法执行之后通知
  3. @AfterThrowing 异常通知
  4. @Around 环绕通知
  5. @AfterReturning 方法返回结果之后通知
    在引入注解里面的格式就是
    @Before(value=“”)value中写的就是我们针对哪个类里面的哪个方法增强
package com.xiaoran.spring.aspectAnno;

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

@Component
@Aspect//开启代理生成对象
public class Userproxy {

    @Before(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void before(){
        System.out.println("前置通知。。。。。。");
    }
    }

3.我们在spring.xml中配置:
我们需要去引入context
打开扫描,在配置文件中开启生成代理对象

<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
    <!--配置扫描-->
      <context:component-scan base-package="com.xiaoran.spring"></context:component-scan>
    <!--配置文件中开启生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

4.最后写一个测试类来查看一下结果

package com.xiaoran.spring.testdemo;

import com.xiaoran.spring.aspectAnno.User;
import com.xiaoran.spring.config.Configxml;
import com.xiaoran.spring.xmlbook.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testproxy {
    @Test
    public void test1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        User user =context.getBean("user",User.class);
        user.add();
    }
    }

我们的得到的结果是
请添加图片描述

注意其他5种方法的执行过程都是一样的,只有一种注解用法有点不同(@Around)环绕注解
环绕注解我们在使用过程中:我的增强类方法中是需要引入一个(ProceedingJoinPoint)参数用它里面的方法(proceed)来调用我们被增强的方法

  @Around(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前执行/......");
        //被增强方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后执行");
    }

其他的不需要改变我们来查看一下结果
请添加图片描述
我还是把所有的注解都实现一下把,大家可以看一下,在Userproxy.java中写

package com.xiaoran.spring.aspectAnno;

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

@Component
@Aspect//开启代理生成对象
public class Userproxy {
    
    @Before(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void before(){
        System.out.println("前置通知。。。。。。");
    }

   @After(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void after(){
        System.out.println("在方法执行之后执行。。。。。。");
    }@AfterThrowing(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void Theowing(){
        System.out.println("异常通知。。。。。。");
    }
    @AfterReturning(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void Runturn(){
        System.out.println("方法返回结果后通知。。。。。。");

    }
    @Around(value = "execution(* com.xiaoran.spring.aspectAnno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前执行/......");
        //被增强方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后执行");
    }

}

注意了注意了,接下来就又是细节操作了
1.如果有两个类都对一个方法做增强,那么我们可以设置一下增强类的优先级
(1)在增强类上面添加注解@order(数字类型值)这里值越小优先级越高

AOP操作(AspectJ在spring.xml中配置通知)

1.创建两个类
2.spring中创建两个类对像book.java和Mybook.java
3.在spring中配置文件的切入点

1.创建book.java类在类中写一个add()方法

package com.xiaoran.spring.xmlbook;
public class Book {
    public void add(){
        System.out.println("这个是adddxxxxxx。。。。。。。。。。");
    }
}

创建Mybook.java在类中写:我们的增强类(buy())

package com.xiaoran.spring.xmlbook;
public class Mybook {
    public void buy(){
        System.out.println("这是我们增强的方法");
    }
}

2.在spring中怕配置:
(1)先用bean标签创建我们的两个对象

  <bean id="book" class="com.xiaoran.spring.xmlbook.Book"></bean>
    <bean id="mybook" class="com.xiaoran.spring.xmlbook.Mybook"></bean>

(2)配置aop增强

<!--配置aop增强-->
    <aop:config>
        <!--切入点id是自己设置,后写的是给哪个类,增强哪个方法-->
        <aop:pointcut id="p" expression="execution(* com.xiaoran.spring.xmlbook.Book.add(..))"/>
        <!--配置切面:这个就是配置我们去增强别人的类 -->
        <aop:aspect ref="mybook![请添加图片描述](https://img-blog.csdnimg.cn/58b528df524e45d0bc20dca1f99ab06c.jpg?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCP5YaJMQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
">
            <!--增强作用在具体的方法上面:method:写的是我们的增强类中的方法名字(增强方法)  pointcut-ref:这	个是引入我们的切入点-->
            <aop:before method="buy" pointcut-ref="p"></aop:before>
        </aop:aspect>
    </aop:config>

请添加图片描述
3.写一个测试类:

  @Test
    public void test2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring2.xml");
        Book user =context.getBean("book",Book.class);
        user.add();
    }

之后的结果为:
请添加图片描述

纯注解开发

1.纯注解开法就是不需要spring.xml,我们就以上面为实列写修改一下来说明
创建一个Configxml.java来替代我们之前写的spring.xml
在这个类中写:@ComponentScan(basePackages = {“com.xiaoran.spring”}),这个就是我们的配置扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)//开启Aspect成为代理对象

package com.xiaoran.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
//配置扫描
@ComponentScan(basePackages = {"com.xiaoran.spring"})
//开启Aspect成为代理对象
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Configxml {

}

在book.java中添加注解@Component

package com.xiaoran.spring.xmlbook;

import org.springframework.stereotype.Component;

@Component
public class Book {
    public void add(){
        System.out.println("这个是adddxxxxxx。。。。。。。。。。");
    }
}

在Mybook.java中添加注解

package com.xiaoran.spring.xmlbook;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect//开启代理对象
public class Mybook {
    @After(value = "execution(* com.xiaoran.spring.xmlbook.Book.add(..))")
    public void buy(){
        System.out.println("这是我们增强的方法");
    }
}

测试类中其他地方不需要去改变,我们只需要去改变测试类中的代码把获取spring.xml的地方改为获取Configxml.class类

@Test
    public void test3(){
        ApplicationContext context=new AnnotationConfigApplicationContext(Configxml.class);
        Book user =context.getBean("book",Book.class);
        user.add();
    }

最后的结果为:
请添加图片描述

JdbcTemplate

1什么jdbcTemplate:spring框架对jdbc进行封装,使用jdbcTemplate方便实现对数据库的操作
2.准备工作:
(1)引入依赖:mysql连接数据库的jar包
请添加图片描述

只需要这5个包但是你也可以全部引入,包去哪找这个问题很重要,传送门
2.在spring.xml中配置mysql数据库连接池,每个人的密码和名字不同,我这里使用的是我的test库

 <!--配置数据库连接池-->
      <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
            <property name="username" value="root"></property>
            <property name="password" value="mysql123456"></property>
      </bean>

3.在spring.xml中配置jdbcTemplate对象,注入DataSource,注意注意这里我们是用set注入大家可以看源码

 <!--配置jdbcTemplate对象,注入DataSource-->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--在这里面我们需要用set注入我们的数据库连接池-->
            <property name="dataSource" ref="datasource"></property>
      </bean>

4.创建service类和dao类
(1)在配置文件中还要记得打开扫描

 <!--配置扫描 -->
      <context:component-scan base-package="com.xiaoran.spring"></context:component-scan>
(2)在service类中注入dao
(3)在dao中注入 JdbcTemplate

5.在mysql中创建一个非常简单的 表test1
在mysql中写

create table test1(
	id int,
    name char(12),
    age int
)

我们的准备工作就完成了

用JdbcTemplate对数据库进行添加操作

我们在创建一个entity包,创建对应我们数据库中的实体
添加一个get和set 和tostring方法

package com.xiaoran.spring.entity;

public class Book {
    private int id;
    private String  name;
    private  int  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;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.我们在service类中创建一个类BookService.java
我们在类中注入dao类
通过Bookservice类去调用我们的添加方法()


@Component
public class BookService {
    @Autowired//注入dao类
    private BookDao bookDao;

    //添加的方法
    public void add(Book book){
        bookDao.add(book);
    }
    }

3.在dao中创建一个BookDao.java接口和BookDaoImple.java来实现接口
BookDao.java

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

在BookDaoImpl.java中写:
在这里就要重点说一下了注意了哟,
我们在这里引入JdbcTemplate 我们使用它里面的一个方法 update(参数1,参数2[ ])
参数1:是我们写的sql语句
参数2:是我们sql语句中问号表示的值,因为有 时我们的问号有多个,所以这是一个数组类

@Component
public class BookdaoImpl implements BookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public  void add(Book book){
        String sql="insert into test1 values (?,?,?)";
        Object[] args={book.getId(),book.getName(),book.getAge()};
        int update=jdbcTemplate.update(sql,args);
        System.out.println(update);//这里我们输出一下影响的行数
  }
   }

4.最后我们在写一个测试类:这里我们添加的是一个对像所以我们需要创建一个book对象用set放值,后面我们在BookDaoImpl.java中用get方法取出值

   @Test
    public void Test(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        Book book=new Book();
        book.setId(1);
        book.setName("小冉好帅");
        book.setAge(20);
        bookService.add(book);
    }

最后我们需要在mysql中查看一下结果

select * from  test1

请添加图片描述
我们简简单单总结一下主要就时我们要记住JdbcTemplate中的这个update()方法的使用;

用JdbcTemplate对数据库进行修改操作

这个和上面没有什么区别,主要区别就是sql语句不同
在BookService中添加一个方法

   //修改的方法
    public void updatebook(Book book){
        bookDao.updatebook(book);
    }

在BookDao.java中添加一个方法

 public void updatebook(Book book);

在BookdaoImpl.java中添加一个实现方法

 @Override
    public void updatebook(Book book){
        String sql="update test1 set name=?,age=? where id=?";
        Object[] args={book.getName(),book.getAge(),book.getId()};
        int update=jdbcTemplate.update(sql,args);
        System.out.println(update);
    }

最后我们写一个测试类:

  @Test
    public void test2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        Book book=new Book();
        book.setName("小芳");
        book.setAge(20);
        book.setId(1);
        bookService.updatebook(book);
    }

结果显示:
请添加图片描述

用JdbcTemplate对数据库进行删除操作

这个和上面没有什么区别,主要区别就是sql语句不同,还有就是我们删除是按照id删除
在BookService中添加一个方法

    //删除的方法
    public void deletebook(int  i){
        bookDao.deletebook(i);
    }

在BookDao.java中添加一个方法

public void deletebook(int i);

在BookdaoImpl.java中添加一个实现方法

  @Override
    public  void deletebook(int i){
        String sql="delete from test1 where id=?";
        int update=jdbcTemplate.update(sql,i);
        System.out.println(update);
    }

最后我们写一个测试类:

  @Test
    public void test3(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        int i=1;
        bookService.deletebook(i);
    }

结果显示:最后全部没有了

查询返回某个值

我们这里的列子是去查看数据库中有几个值count

在BookService中添加一个方法

  //返回查询某个对象
    public  Book selectbook(int i){
        Book book=bookDao.seletbook(i);
        return book;
    }

在BookDao.java中添加一个方法

 public int  selectint();

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
queryForObject(第一个参数,第二参数)方法,返回某个值
第一个参数是:sql语句
第二个参数是:class< T > requiredType 返回类型的class,返回的是什么类型就写什么类型

  @Override
    public int selectint(){
        String sql="select count(*) from test1";
        Integer integer=jdbcTemplate.queryForObject(sql,Integer.class);
        return integer;
    }

最后我们写一个测试类:

  @Test
    public void test3(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        int i=1;
        bookService.deletebook(i);
    }

结果显示:

请添加图片描述

查询返回对象用JdbcTemplate

在BookService中添加一个方法

  //返回查询某个对象
    public  Book selectbook(int i){
        Book book=bookDao.seletbook(i);
        return book;
    }

在BookDao.java中添加一个方法

 public Book  seletbook(int i);

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
queryForObject(第一个参数,第二参数第三个参数)方法,查询返回对象
第一个参数是:sql语句
第二个参数是:RowMapper接口,返回不同类型,使用这个接口里面的实现类完成数据
new BeanPropertyRowMapper<这里面写的是我们返回对象的名字>(返回对象.class)
第三个参数是:问号中的值

 @Override
    public Book seletbook(int i){
        String sql="select * from test1 where id=?";
        Book book=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),i);
        return book;
    }

最后我们写一个测试类:

  @Test
    public void test5(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        int id=1;
        Book book=bookService.selectbook(id);
        System.out.println(book);
    }

结果显示:

请添加图片描述

查询返回列表

在BookService中添加一个方法

  //查询返回列表
    public List<Book> select(){
        List<Book> books=bookDao.select();
        return books;
    }

在BookDao.java中添加一个方法

  public List<Book> select();

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
query(第一个参数,第二个参数),查询返回列表
第一个参数是:sql语句
第二个参数是:RowMapper接口,返回不同类型,使用这个接口里面的实现类完成数据
new BeanPropertyRowMapper<这里面写的是我们返回对象的名字>(返回对象.class)

  @Override
    public List<Book> select(){
        String sql="select * from test1";
        List<Book> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));
        return list;
    }

最后我们写一个测试类:

     @Test
    public void test6(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        List<Book> list=bookService.select();
        System.out.println(list);
    }

结果显示:

请添加图片描述

JdbcTemplate操作数据库实现批量操作 添加

在BookService中添加一个方法

   //实现对返回列表的批量处理
    public void addall(List<Object[]> bat){
        bookDao.addall(bat);
    }

在BookDao.java中添加一个方法

  public void addall(List<Object[]> bat);

在BookdaoImpl.java中添加一个实现方法:在这里面我们要实现JdbcTemplate里面的
batchUpdate(第一个参数,第二个参数),查询返回列表
第一个参数是:sql语句
第二个参数是:List<Object[]> batchArgs 这是一个集合放的是我们?的值,这里面可以放很多组

   @Override
    public void addall(List<Object[]> bat){
        String sql="insert into test1 values(?,?,?)";
        //调用batchupdate(sql,这是一个集合放的是我们?的值,这里面可以放很多组)
        int[] ints=jdbcTemplate.batchUpdate(sql,bat);
        System.out.println(Arrays.toString(ints));
    }

最后我们写一个测试类:

   @Test
    public void test7(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        //创建一个 列表 用来存放我们的插入数据
        List<Object[]> list= new ArrayList<>();
        Object[] o1={3,"java",18};
        Object[] o2={4,"mysql",18};
        Object[] o3={5,"c++",20};
        list.add(o1);
        list.add(o2);
        list.add(o3);
        //调用批量处理
        bookService.addall(list);

    }

批量修改和删除和上面差不多

------------------------------------------------------------------------------------------

接下来我们就把全部补齐
在BookService中添加一个方法

  package com.xiaoran.spring.service;

import com.xiaoran.spring.dao.BookDao;
import com.xiaoran.spring.entity.Book;
import org.aspectj.lang.annotation.After;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

//调用方法

@Component
public class BookService {
    @Autowired//注入dao类
    private BookDao bookDao;

    //添加的方法
    public void add(Book book){
        bookDao.add(book);
    }
    //修改的方法
    public void updatebook(Book book){
        bookDao.updatebook(book);
    }
    //删除的方法
    public void deletebook(int  i){
        bookDao.deletebook(i);
    }
    //查询返回结果
    public int selectint(){
        int count=bookDao.selectint();
        return count;
    }
    //返回查询某个对象
    public  Book selectbook(int i){
        Book book=bookDao.seletbook(i);
        return book;
    }
    //查询返回列表
    public List<Book> select(){
        List<Book> books=bookDao.select();
        return books;
    }
    //实现对返回列表的批量处理
    public void addall(List<Object[]> bat){
        bookDao.addall(bat);
    }
    //实现对列表的批量修改
    public void updateall(List<Object[]> bat){
        bookDao.updateall(bat);
    }
    //实现对数据库的批量删除
    public void deleteall(List<Object[]> bat){
        bookDao.deleteall(bat);
    }

}



在BookDao.java中添加一个方法

  package com.xiaoran.spring.dao;

import com.xiaoran.spring.entity.Book;

import java.util.List;

public interface BookDao {
    public void add(Book book);
    public void deletebook(int i);
     public void updatebook(Book book);
      public int  selectint();
    public Book  seletbook(int i);
    public List<Book> select();
    public void addall(List<Object[]> bat);
    public void updateall(List<Object[]>bat);
    public void deleteall(List<Object[]> list);
}

在BookdaoImpl.java中:

 package com.xiaoran.spring.dao;

import com.xiaoran.spring.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

//这里面写的对数据库的操作
@Component
public class BookdaoImpl implements BookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public  void add(Book book){
        String sql="insert into test1 values (?,?,?)";
        Object[] args={book.getId(),book.getName(),book.getAge()};
        int update=jdbcTemplate.update(sql,args);
        System.out.println(update);
    }
    @Override
    public void updatebook(Book book){
        String sql="update test1 set name=?,age=? where id=?";
        Object[] args={book.getName(),book.getAge(),book.getId()};
        int update=jdbcTemplate.update(sql,args);
        System.out.println(update);
    }
    @Override
    public  void deletebook(int i){
        String sql="delete from test1 where id=?";
        int update=jdbcTemplate.update(sql,i);
        System.out.println(update);
    }
 @Override
    public int selectint(){
        String sql="select count(*) from test1";
        Integer integer=jdbcTemplate.queryForObject(sql,Integer.class);
        return integer;
    }
    @Override
    public Book seletbook(int i){
        String sql="select * from test1 where id=?";
        Book book=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),i);
        return book;
    }
    @Override
    public List<Book> select(){
        String sql="select * from test1";
        List<Book> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));
        return list;
    }
    @Override
    public void addall(List<Object[]> bat){
        String sql="insert into test1 values(?,?,?)";
        //调用batchupdate(sql,这是一个集合放的是我们?的值,这里面可以放很多组)
        int[] ints=jdbcTemplate.batchUpdate(sql,bat);
        System.out.println(Arrays.toString(ints));
    }
    @Override
    public void updateall(List<Object[]> list){
        String sql="update test1 set name=?,age=? where id=?";
       int[] i= jdbcTemplate.batchUpdate(sql,list);
       System.out.println(Arrays.toString(i));
    }
    @Override
    public void deleteall(List<Object[]> list){
        String sql="delete from test1 where id=?";
        int[] i =jdbcTemplate.batchUpdate(sql,list);
        System.out.println(Arrays.toString(i));
    }

}

最后我们写一个测试类:

 package com.xiaoran.spring.testdemo;

import com.xiaoran.spring.entity.Book;
import com.xiaoran.spring.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;

public class test {
    @Test
    public void Test(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        Book book=new Book();
        book.setId(1);
        book.setName("小冉好帅");
        book.setAge(20);
        bookService.add(book);
    }

    @Test
    public void test2(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        Book book=new Book();
        book.setName("小芳");
        book.setAge(20);
        book.setId(1);
        bookService.updatebook(book);
    }
    @Test
    public void test3(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        int i=1;
        bookService.deletebook(i);
    }
    @Test
    public void test4(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
       int  i =bookService.selectint();
       System.out.println(i);
    }
    @Test
    public void test5(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        int id=1;
        Book book=bookService.selectbook(id);
        System.out.println(book);
    }
    @Test
    public void test6(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        List<Book> list=bookService.select();
        System.out.println(list);
    }
    @Test
    public void test7(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        //创建一个 列表 用来存放我们的插入数据
        List<Object[]> list= new ArrayList<>();
        Object[] o1={3,"java",18};
        Object[] o2={4,"mysql",18};
        Object[] o3={5,"c++",20};
        list.add(o1);
        list.add(o2);
        list.add(o3);
        //调用批量处理
        bookService.addall(list);

    }
    @Test
    public void test8(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        //创建一个 列表 用来存放我们的插入数据
        List<Object[]> list= new ArrayList<>();
        Object[] o1={"java 小冉帅",18,3};
        Object[] o2={"mysql 小冉帅",18,4};
        Object[] o3={"c++ 小冉帅",20,5};
        list.add(o1);
        list.add(o2);
        list.add(o3);
        //调用批量处理
        bookService.updateall(list);

    }
    @Test
    public void test9(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
        BookService bookService=context.getBean("bookService",BookService.class);
        //创建一个 列表 用来存放我们的插入数据
        List<Object[]> list= new ArrayList<>();
        Object[] o1={3};
        Object[] o2={4};
        Object[] o3={5};
        list.add(o1);
        list.add(o2);
        list.add(o3);
        //调用批量处理
        bookService.deleteall(list);

    }
}

  

我们对数据库的操作就结束了,多练习其实不难

事务

1.什么是事务,事务是数据库操作最基本单元,逻辑上的一组操作,要么都成功,如果有一个失败那么所有操作都会失败。
2.事务的作用很广泛如:我们的银行转账,必须是一个人扣钱了一个人才可以收到钱,如果转载过程中断电了那么就会转账失败。
3.我们创建一个简单的环境来实现:转帐环境搭建
(1)创建一个service类和dao类
(2)在dao类中写两个方法,一个是addmoney方法增加钱,一个是reduceMoney方法少钱的
(3)在service类中写:创建转钱的方法(1)调用dao中的两个方法
(2)创建一个数据库我们在数据库中写一个表用来记录转帐
mysql代码:

create table account(
	id int,
    name char(12),
    money int
)

我们在创建的表中添加两个人小冉和小芳用来模拟他们两的交易,假设他们一开始钱都是1000

insert into account values(1,'小冉',1000)
insert into account values(2,'小芳',1000)

请添加图片描述

1.在dao中创建一个Userdao.java接口,在接口中写两个方法

package com.xiaoran.spring.dao;

public interface Userdao {
    public void addmoney();//多钱
    public void reduceMoney();//少钱
}

在dao中创建一个实现上面接口的方法:
在这个方法中实现接口中的方法我们实现 " 加钱" 或者 “少钱” 的方法就是直接修改数据库中我们余额

package com.xiaoran.spring.dao;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserdaoImpl implements Userdao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    //多钱
    public void addmoney(){
    String sql="update account set money=money+? where name=? ";
    jdbcTemplate.update(sql,100,"小冉");

    }
    //少钱
    public void reduceMoney(){
        String sql="update account set money=money-? where name=? ";
        jdbcTemplate.update(sql,100,"小芳");
    }
}

3.我们创建一个UserService.java类在类中写:

package com.xiaoran.spring.service;

import com.xiaoran.spring.dao.Userdao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class Userservice {
    //注入dao
    @Autowired
    private Userdao userdao;
    //转载方法
    public void accountmoney(){
             //少钱
            userdao.reduceMoney();
            //多钱
            userdao.addmoney();

    }


}

4.我们需要在spring.xml中配置:配置扫描,配置数据库连接池,配置配置jdbcTemplate对象,注入DataSource

<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
       http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd">

      <!--配置扫描 -->
      <context:component-scan base-package="com.xiaoran.spring"></context:component-scan>
      <!--配置数据库连接池-->
      <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
            <property name="username" value="root"></property>
            <property name="password" value="mysql123456"></property>
      </bean>

      <!--配置jdbcTemplate对象,注入DataSource-->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--在这里面我们需要用set注入我们的数据库连接池-->
            <property name="dataSource" ref="datasource"></property>
      </bean>
</beans>

最后我们写一个测试类:

  @Test
    public void test(){
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        Userservice  userservice=context.getBean("userservice",Userservice.class);
        userservice.accountmoney();
    }

执行之后我们查看数据库中的结果:
在mysql中写

select * from  account;

结果显示:
请添加图片描述

事实证明我们的方法是有效的;但是这是我们所说的理想情况,在实际的过程中会有很多未知的变化,
接下来我们举个列子:
我们在UserService.java中添加一个异常,模拟我们在实际过程中出现了异常:

package com.xiaoran.spring.service;

import com.xiaoran.spring.dao.Userdao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class Userservice {
    //注入dao
    @Autowired
    private Userdao userdao;
    //转载方法
    public void accountmoney(){
             //少钱
            userdao.reduceMoney();
            //模拟异常
            int i=10/0;
            //多钱
            userdao.addmoney();

    }


}

请添加图片描述
接下来我们在执行就会发现,发现我们的小芳钱少了,而小冉的钱也没有增加,钱去哪了呢???
我们用之前的测试方法执行一下,结果显示为
请添加图片描述
所以我们就必须得引入事务啦

引入事务

1.在spring中进行事务管理操作
(2)有两种方法:编程式事务管理(了解)和声明式事务管理(使用多)
声明式事务管理:可以分为注解实现,和xml配置实现

2.在spring中进行声明事务管理(底层使用AOP原理)

事务操作(注解声明式事务管理)

1.我们在UserService.java上面添加一个注解:@Transactional 开启事务

2.我们需要在spring.xml中配置事务管理器:DataSourceTransactionManager,这里面我们需要用set注入我们的数据库连接池

  <!--配置事务管理器-->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--注入数据源-->
            <property name="dataSource" ref="datasource"></property>
      </bean>

2.开启事务注解,前提我们需要在顶部引入tx和aop
请添加图片描述

<!--开启事务注解-->
      <!--transaction-manager="transactionManager" 指定我们的事务管理器-->
      <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

请添加图片描述
3.接下来我们在重新测试:
我们先把mysql中的数据还原一下

update account set money=1000 where name='小芳'
update account set money=1000 where name='小冉'

请添加图片描述
最后用以前的测试方法测试一下

 @Test
    public void test(){
        ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
        Userservice  userservice=context.getBean("userservice",Userservice.class);
        userservice.accountmoney();
    }

在数据库中查看发现:

select * from account

测试结果为:
请添加图片描述
我们在添加了事务之后,只要有一个错误就不会提交事务

我们来看一下这个注解的用法吧:
@Transactional注解里面可以写6个值分别是

  1. Propagation :事务传播行,多事物直接或间接调用,这个过程中事务时如何管理的
    propagation.REQUIRED:如果有事务在运行,当前方法就在这个事务中运行,否则就在启动一个新事物,并在自己的事务中运行;(默认是这个)
    propagation.REQUIRED_NEW:当前的方法必须启动新事物并在它自己的事务内运行,如果有事务在运行应该将它先挂起
  2. Ioslation :事务隔离,多事物之间操作如果不设置隔离性,就会产生很多问题如:脏读,重复读,虚度
    我们可以通过设置事务的隔离级别来解决问题
    默认是:Ioslation.REDATABLEREAD(可重复读)
  3. tiemout :超时间,默认是-1没有时间限制,超过我们设置的时间就会提交,不提交就会回滚
  4. readonly :是否只读,默认为false,可以查询可以添加修改删除操作,如果把值设置为True之后只能进行查询
  5. rollbackFor:回滚,设置出现哪些异常进行事务回滚
  6. norollbackFor:不回滚,设置出现哪些异常不进行事务回滚

事务操作(基于注解实现)

1.在xml中配置
(1)配置事务管理器
(2)配置事务通知
(3)配置切入点和切面

我们在spring.xml中配置:
配置事务管理器

  <!--配置事务管理器-->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--注入数据源-->
            <property name="dataSource" ref="datasource"></property>
      </bean>

配置事务通知

  <tx:advice id="txadvice">
            <!--配置事务参数-->
            <tx:attributes>
                  <!--
                        name=""这里写的是:指定哪种方法上面添加事务
                        propagation="" 这里面写的是:指定事务
                  -->
                  <tx:method name="accountmoney" propagation="REQUIRED"></tx:method>
            </tx:attributes>
      </tx:advice>

配置切面和切面

  <!--配置切入点和 切面-->
      <aop:config>
            <!--配置切入点-->
            <aop:pointcut id="pt" expression="execution(* com.xiaoran.spring.service.Userservice.accountmoney(..))"></aop:pointcut>
            <!--配置切面advice-ref="txadvice" 这里面写的是把我们的通知配置进来
            pointcut-ref="pt"引入切入点
            -->
            <aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor>
      </aop:config>

请添加图片描述
之后我们去掉在UserService.java中的注解@Transactional,执行的结果还是和之前的是一样的

完全纯注解开发

1.创建一个config包在包中创建一个Txcongifg.java类
(1)在类中添加注解@Configuration//配置类
@ComponentScan(basePackages = “com.xiaoran.spring”)//开启扫描
@EnableTransactionManagement//开启事务注解

package com.xiaoran.spring.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration//配置类
@ComponentScan(basePackages = "com.xiaoran.spring")//开启扫描
@EnableTransactionManagement//开启事务注解
public class Txcongifg {
    //配置数据库连接池
    @Bean
    public DruidDataSource getdruidDataSource(){
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("mysql123456");
        return dataSource;
    }


    //配置jdbcTemplate对象,注入datasource
    @Bean
    public JdbcTemplate jdbctemplat(DataSource dataSource){
        JdbcTemplate jdbcTemplate=new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
    //-配置事务管理器
    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

之后我们写一个测试类:

package com.xiaoran.spring.Test;


import com.xiaoran.spring.config.Txcongifg;
import com.xiaoran.spring.service.Userservice;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Testdemo2 {
    @Test
    public void test2(){
        ApplicationContext context =new AnnotationConfigApplicationContext(Txcongifg.class);
        Userservice  userservice=context.getBean("userservice",Userservice.class);
        userservice.accountmoney();
    }

}

执行的结果和之前的还是一样的,大家可以去多练习一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

O_0..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值