Spring 简介(03)

Spring 简介(03)

9 AOP切面编程

9.4 使用Cglib代理

Cglib动态代理它不管目标对象有没有实现接口.它都可以实现代理技术.

Cglib动态代理是通过修改目标对象的字节码程序产生一个子类.生成一个代理对象实例(增强).

增强 extends 目标

Cglib产生的代理对象是目标对象(增强)的子类

jar:com.springsource.net.sf.cglib-2.2.0.jar
public class CglibProxyFactory {

    public static Object createCglibProxy(Object target){
        // 增强器 它负责产生一个Cglib代理对象实例
        Enhancer enhancer = new Enhancer();
        // 指定要修改哪个目标对象的字节码程序
        enhancer.setSuperclass(target.getClass());
        // 设置方法拦截器==跟InvocationHandler接口功能一样,
        // 是代理对象调用方法时就会执行的接口(专门对目标方法进行增强)
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * 只要代理对象方法调用,就会执行intercept()方法
             * @param proxy         代理对象实例 <br/>
             * @param method        调用的方法的反射对象 <br/>
             * @param args          调用方法时传递的参数 <br/>
             * @param methodProxy   方法反射对象的代理对象<br/>
             * @return  返回值是代理对象调用方法的返回值
             * @throws Throwable
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object result = null;
                try {
                    // 前置增强
                    LogUtils.logBefore(method.getName(),args);
                    result = method.invoke(target, args);
                    // 后置增强
                   LogUtils.logAfterReturning(method.getName(),result);

                } catch (Exception e) {
                    // 异常增强
                    LogUtils.logAfterThrowing(method.getName(),e);
                    throw new RuntimeException(e);
                }
                return result;
            }
        });
        // 创建Cglib代理对象实例
       return enhancer.create();
    }
}

优点:在没有接口的情况下,同样可以实现代理的效果。

缺点:同样需要自己编码实现代理全部过程。

但是为了更好的整合Spring框架使用。所以我们需要学习一下Spring 的AOP 功能。也就是学习Spring提供的代理功能。

面试:cglib(有无接口都可,但是目标不能是final修饰),jdk动态代理(必须有接口)

9.5 什么是AOP

AOP是面向切面编程。

全称:Aspect Oriented Programming

面向切面编程指的是:程序是运行期间,动态地将某段代码插入到原来方法代码的某些位置中。

利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,从而提高开发效率,减少冗余代码的编写,方便后期维护

9.6 使用Spring实现AOP简单切面编程

目标:使用spring方式实现动态代理

目标:使用spring方式实现动态代理

需要导哪些包:

  • junit_4.12.jar
  • org.hamcrest.core_1.3.0.jar
  • spring-test-5.2.5.RELEASE.jar
  • spring-aop-5.2.5.RELEASE.jar
  • spring-aspects-5.2.5.RELEASE.jar
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
  • spring-beans-5.2.5.RELEASE.jar
  • spring-context-5.2.5.RELEASE.jar
  • spring-core-5.2.5.RELEASE.jar
  • spring-expression-5.2.5.RELEASE.jar
  • spring-jcl-5.2.5.RELEASE.jar

代码:
application.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"
       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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--
        配置包扫描
    -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>

    <!--
        aop:aspectj-autoproxy 跟AOP注解组合使用。
    -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

LogUtils :

package com.atguigu.utils;

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

import java.util.Arrays;

@Component
/**
 *  @Aspect 表示我是一个切面类
 */
@Aspect
public class LogUtils {

    /**
     *  切入点的复用
     */
    @Pointcut("execution(public int com.atguigu.pojo.Calculator.*(int,int))")
    public static void pointcut1(){}

    @Before(value = "pointcut1()" )
    public static void logBefore(JoinPoint joinPoint) {
        System.out.println(" 前置通知 logBefore() 方法名是 :" + joinPoint.getSignature().getName()
        +"参数是 :" + Arrays.asList(joinPoint.getArgs()));
    }

    @After(value = "execution(public int com.atguigu.pojo.Calculator.*(int,int))")
    public static void logAfter() {
        System.out.println(" 后置通知 " );
    }

    /**
     * @AfterReturning 表示返回通知
     */
    @AfterReturning(value = "execution(public int com.atguigu.pojo.Calculator.*(int ,int))",returning = "result")
    public static void logAfterReturning(JoinPoint joinPoint , Object result) {
        System.out.println(" 返回通知 方法名是 :" +
                joinPoint.getSignature().getName() + "返回值是 :" + result);
    }

    /**
     * @AfterThrowing 这是异常通知
     */
    @AfterThrowing(value = "execution(public int com.atguigu.pojo.Calculator.*(int ,int))",throwing = "e")
    public static void logAfterThrowing(JoinPoint joinPoint,Exception e) {
        System.out.println(" 异常通知 方法名是 :" + joinPoint.getSignature().getName()
        + ",异常是 :" + e);
    }
}

test :

/**
 *  @ContextConfiguration 表示是位置 , 表示Spring 容器配置文件的路径
 */
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest {

    @Autowired
    Calculation Calculation;

    @Test
    public void test01(){
        Calculation.add(1,1);

        System.out.println("====================");
        Calculation.div(100,0);
    }
}

9.7 AOP编程的专业术语

目标(Target)

目标对象就是被关注的对象。

*连接点(Joinpoint)

连接点指的是目标中可以被增强的方法,叫连接点。

*切入点(pointcut)

切入点指的是目标中已经增强的方法,叫切入点。

横切关注点/切入点

增强的方法中,增强的位置

比如前置位置,后置位置,异常位置。和返回值位置。这些都叫横切关注点。

*通知/增强(Advice)

通知就是增强的代码。比如前置增强的代码。后置增强的代码。异常增强代码。这些就叫通知

*切面(Aspect)

包含有通知代码的类叫做切面

代理(Proxy)

增强之前是目标,增强之后是代理

9.8 Spring切面中的代理对象

在Spring中,可以对有接口的对象和无接口的对象分别进行代理。在使用上有些细微的差别。

<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--扫描注解包-->
    <context:component-scan base-package="com.atguigu"/>

    <!--
        aop:aspectj-autoproxy:面向切面必备标签
        让@Aspect 生效
        expose-proxy:让代理类暴露出来
        proxy-target-class:增强的类型
        true: 使用cglib代理
        false: 根据有无接口框架自动选择是cglib,还是jdk代理
    -->
    <aop:aspectj-autoproxy/>
</beans>

1 : 有接口的时候选择的是jdk动态代理

9.9 Spring 的切入点表达式

@PointCut切入点表达式语法格式是: execution(访问权限 返回值类型 方法全限定名(参数类型列表))

execution(****public int**** com.atguigu.pojo.Calculator.add(****int****,****int****))

public 是访问权限

int 是返回值类型

com.atguigu.pojo.Calculator.add 是方法全限定名

(int,int) 参数类型列表

限定符:

*表示任意的意思:

  1. 匹配某全类名下,任意或多个方法。

*execution(public int com.atguigu.pojo.Calculator.*(int,int))*

以上的星表示任意的方法名

*execution(public int com.atguigu.pojo.Calculator.save*(int,int))*

以上的星表示。方法名以save字符串打头,后面任意

  1. 在Spring中只有public权限能拦截到,访问权限可以省略(访问权限不能写*)。

*execution(public int com.atguigu.pojo.Calculator.add(int,int))*

public是可以省略的

*execution(int com.atguigu.pojo.Calculator.add(int,int))*

  1. 匹配任意类型的返回值,可以使用 * 表示

*execution(public * com.atguigu.pojo.Calculator.add(int,int))*

以上的星,表示返回值是任意类型

  1. 匹配任意子包。

*execution(public int com.atguigu.*.Calculator.add(int,int))*

以上的星,表示包名只要是com.atguigu.子包都可以

  1. 任意类型参数

*execution(public int com.atguigu.pojo.Calculator.add(int,*))*

表示第二个参数的类型不限制。

****…****:可以匹配多层路径,或任意多个任意类型参数

  1. 任意层级的包

*execution(public int com.atguigu…Calculator.add(int,int))*

才上的点点****…****,表示任意层级的子包

  1. 任意个,任意类型的参数

*execution(public int com.atguigu.pojo.Calculator.add(…))*

以上点点,表单任意个,任意类型的参数

模糊匹配:

// 表示任意返回值,任意方法全限定符,任意参数

execution(* *(…))

// 表示任意返回值,任意包名+任意方法名,任意参数

execution(* .(…))

精确匹配:

*execution(public int com.atguigu.pojo.Calculator.add(int,int))*

public 是访问权限 必须是public

int 返回值必须是int

*com.atguigu.pojo.Calculator.add* *包名+类名+方法名。必须是add*

*(int,int)* *两个参数,类型必须都是int*

切入点表达式连接:&& 、||

// 表示需要同时满足两个表达式

​ @Before(“execution(public int com.atguigu.aop.Calculator.add(int, int))”

​ + " && "

+ “execution(public * com.atguigu.aop.Calculator.add(…))”)

// 表示两个条件只需要满足一个,就会被匹配到

​ @Before(“execution(public int com.atguigu.aop.Calculator.add(int, int))”

​ + " || "

​ + “execution(public * com.atguigu.aop.Calculator.a*(int))”)

9.10 Spring的通知执行顺序

前置通知

后置通知

返回通知

异常通知

Spring通知的执行顺序是:

正常情况:

前置通知====>>>>目标方法====>>>>后置通知=====>>>>返回值之后

异常情况:

前置通知====>>>>目标方法====>>>>后置通知=====>>>>抛异常通知

LogUtils :

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;


@Component
@Aspect
public class LogUtils {

    @Pointcut("execution(*  com.atguigu.service.Impl.Calculator.*(..))")
    public void printCut(){}

    /**
     * 切入点表达式可以用一些通配符去使用
     * 1) 匹配某全类名下,任意或多个方法。
     * public int com.atguigu.service.impl.Calculator.*(int,int):*表示所有方法
     * 2) 访问权限可以忽略
     * int com.atguigu.service.impl.Calculator.div(int,int)
     * 3) 匹配任意类型的返回值,可以使用 * 表示
     * public * com.atguigu.service.impl.Calculator.div(int,int)
     * 4) 匹配任意一层子包。
     * public int com.atguigu.service.*.Calculator.div(int,int)
     * 5) 任意类型参数
     * public int com.atguigu.service.impl.Calculator.div(*,int)
     * 1) 任意层级的包
     * public int com.atguigu.service..Calculator.div
     * 2) 任意个数类型的参数
     * public int com.atguigu.service.impl.Calculator.div(..)
     * <p>
     * 模糊匹配:(绝不使用)
     * <p>
     * ||   &&
     * 常用:
     * * 方法的路径(有可能是某个包下的所有类和所有方法,有可能是某个包下的指定类的所有方法) (..)
     * 业务类型:
     * 抓取用户行为,存入日志表
     * <p>
     * 通知执行顺序:
     * 无异常: 前置----后置-----返回
     * 异常:  前置----后置----异常
     * JoinPoint:切入点对象,里面封装了切入点的一些属性
     */
    @Before(value = "printCut()")
    public static void logBefore(JoinPoint joinPoint) {
        System.out.println(" 前置通知 ,执行的方法名称是:" + joinPoint.getSignature().getName()
                + "参数是 :" + Arrays.asList(joinPoint.getArgs()));
    }


    @After(value = "printCut()")
    public static void logAfter(JoinPoint joinPoint) {
        System.out.println("  后置通知  ,执行的方法名称是:" + joinPoint.getSignature().getName()
                + "参数是 :" + Arrays.asList(joinPoint.getArgs()));
    }

    /**
     * 获取方法的返回值 returning
     * @param joinPoint
     */
    @AfterReturning(value = "printCut()",returning = "result")
    public static void logAfterReturning(JoinPoint joinPoint , Object result) {
        System.out.println("  最终通知  ,执行的方法名称是:" + joinPoint.getSignature().getName()
                + "参数是 :" + Arrays.asList(joinPoint.getArgs()) +",返回值是:" + result );
    }

    /**
     * 获取异常信息: e
     * @param joinPoint
     */
    @AfterThrowing(value = "printCut()",throwing = "e")
    public static void logAfterThrowing(JoinPoint joinPoint,Throwable e) {
        System.out.println(" 异常通知 ,执行的方法名称是:" + joinPoint.getSignature().getName()
                + "参数是 :" + Arrays.asList(joinPoint.getArgs()) +",异常是:" + e );
    }

}

test :

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @RunWith 表示使用Spring 扩展的Junit测试类来测试代码
 * @ContextConfiguration : 注解的作用是指定Spring容器需要的配置文件路径
 * classes : 放入配置文件类
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AopTest {

    @Autowired
    private Calculation calculation;

    @Autowired
    private LogUtils logUtils;

    @Test
    public void test() {
        calculation.div(1,1);
    }
}

9.11 切入点表达式的复用

9.12 多个切面的执行顺序

当我们有多个切面,多个通知的时候:

  1. 通知的执行顺序默认是由切面类的字母先后顺序决定。
  2. 在切面类上使用@Order注解决定通知执行的顺序(值越小,越先执行)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1yxpe9tx-1608196301378)(file:///C:\Users\psd\AppData\Local\Temp\ksohtml1616\wps3.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XOvuU2RH-1608196301378)(D:/JavaEE_Second/javaSSM/ssm_class/day06_spring03/note/spring03.assets/wps8.jpg)]

9.13 如何基于xml 配置aop程序

1 拷贝原来的代码

2 删除原来代码中所有注解配置

3 到applicationContext.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"
       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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置目标对象 -->
    <bean class="com.atguigu.service.Impl.Calculator" id="calculator"/>
    <!-- 配置切面类对象实例 -->
    <bean class="com.atguigu.utils.LogUtils" id="logUtils"/>
    
    <!--
    aop配置
    -->
    <aop:config>
        <!--
            aop:aspect配置切面类 相当于注解@Aspect
                ref引用哪个类做为切面类
        -->
        <!--
            aop:pointcut 定义切入点表达式
                id 是唯一标识(方便引用)
                expression 切入点表达式
        -->
        <aop:pointcut id="point" expression="execution(* com.atguigu.service.Impl.Calculator.*(..))"/>


        <aop:aspect ref="logUtils">
              <!-- 前置通知 -->
<!--            <aop:before method="logBefore" pointcut-ref="point"/>-->
            <!-- 后置通知 -->
<!--            <aop:after method="logAfter" pointcut-ref="point"/>-->
            <!-- 返回结果 -->
<!--            <aop:after-returning method="logAfterReturning" pointcut-ref="point" returning="result"/>-->
            <!-- 异常处理 -->
<!--            <aop:after-throwing method="logAfterThrowing" pointcut-ref="point" throwing="e"/>-->

            <!-- 环绕通知 -->
            <aop:around method="logAround" pointcut-ref="point"/>
<!--            <aop:around method="-->
        </aop:aspect>
    </aop:config>
</beans>

9.14 纯注解

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @EnableAspectJAutoProxy( proxyTargetClass = true) == <aop:auto-proxy/>
 * @EnableAspectJAutoProxy默认是false , 执行的是jdkProxy
 */

//proxyTargetClass = true 都是用的Cglib
@Configuration  // 表明是一个配置类
@ComponentScan("com.atguigu")  // 配置包扫描
@EnableAspectJAutoProxy   // 开启注解版AOP的功能
public class AopConfig {
}

10 Spring之数据访问

10.1 Spring数据访问工程环境搭建

  • druid-1.1.9.jar
  • junit_4.12.jar
  • mysql-connector-java-5.1.37-bin.jar
  • org.hamcrest.core_1.3.0.jar
  • spring-aop-5.2.5.RELEASE.jar
  • spring-beans-5.2.5.RELEASE.jar
  • spring-context-5.2.5.RELEASE.jar
  • spring-core-5.2.5.RELEASE.jar
  • spring-expression-5.2.5.RELEASE.jar
  • spring-jcl-5.2.5.RELEASE.jar
  • spring-jdbc-5.2.5.RELEASE.jar
  • spring-orm-5.2.5.RELEASE.jar
  • spring-test-5.2.5.RELEASE.jar
  • spring-tx-5.2.5.RELEASE.jar

10.2 Spring之jdbcTemplate 使用

在Spring中提供了对jdbc的封装类叫JdbcTemplate。

它可以很方便的帮我们执行sql语句,操作数据库。

先准备单表的数据库数据

CREATE DATABASE IF NOT EXISTS jdbctemplate DEFAULT CHARSET utf8;

use jdbctemplate;
CREATE TABLE `employee` (
`id` int(11) primary key AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`salary` decimal(11,2) DEFAULT NULL
);

insert into `employee`(`id`,`name`,`salary`) 
values (1,'李三',5000.23),(2,'李四',4234.77),(3,'王五',9034.51),
(4,'赵六',8054.33),(5,'孔七',6039.11),(6,'曹八',7714.11);

select * from employee;

jdbc.properties

user=root
password=root
url=jdbc:mysql://localhost:3306/jdbctemplate?characterEncoding=UTF-8
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

JdbcTemplate的使用需要在applicationContext.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"
       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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 导入jdbc.properties -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 配置包扫描 -->
    <context:component-scan base-package="com.atguigu"/>
    <!-- 数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${user}"/>
        <property name="password" value="${password}"/>
        <property name="url" value="${url}"/>
        <property name="initialSize" value="${initialSize}"/>
        <property name="maxActive" value="${maxActive}"/>
        <property name="driverClassName" value="${driverClassName}"/>
    </bean>

    <!-- 配置Spring提供的jdbcTemplate工具类执行sql语句 -->
    <bean class="org.springframework.jdbc.core.JdbcTemplate"
          id="jdbcTemplate">
        <!-- 配置数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--
        配置可执行具名|命名参数的sql的jdbcTemplate
     -->
    <bean class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"
          id="namedParameterJdbcTemplate">
        <constructor-arg index="0" ref="dataSource"/>
    </bean>


</beans>

实验3:批量插入

实验4:查询id=5的数据库记录,封装为一个Java对象返回

实验5:查询salary>4000的数据库记录,封装为List集合返回

实验6:查询最大salary

实验7:使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值

实验8:重复实验7,以SqlParameterSource形式传入参数值

实验9:创建Dao,自动装配JdbcTemplate对象

实验10:通过继承JdbcDaoSupport创建JdbcTemplate的Dao

package com.atguigu.test;

import com.atguigu.dao.EmployeeDao;
import com.atguigu.pojo.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class JdbcTemplateTest {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private DataSource dataSource;

    @Test
    public void test() throws SQLException {
        System.out.println(jdbcTemplate);
        // 测试数据库是否连接成功
        //  System.out.println(dataSource.getConnection());
        /**
         *  实验2:将id=5的记录的salary字段更新为1300.00
         *  实验3:批量插入
         *  实验4:查询id=5的数据库记录,封装为一个Java对象返回
         *  实验5:查询salary>4000的数据库记录,封装为List集合返回
         *  实验6:查询最大salary
         *  实验7:使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值
         *  实验8:重复实验7,以SqlParameterSource形式传入参数值
         *  实验9:创建Dao,自动装配JdbcTemplate对象
         *  实验10:通过继承JdbcDaoSupport创建JdbcTemplate的Dao
         */
    }

    @Autowired
    EmployeeDao employeeDao;
    @Test
    public void Test9(){
        // 创建Dao,自动装配JdbcTemplate对象
        System.out.println(employeeDao.selectOne(5));
    }



    @Test
    public void Test8(){
        // 重复实验7,以SqlParameterSource形式传入参数值
        String sql = "insert into employee(`name`,`salary`)values(:name,:salary)";
        Employee employee = new Employee(null, "爱你么么哒", new BigDecimal("6666.00"));
        namedParameterJdbcTemplate.update(sql,new BeanPropertySqlParameterSource(employee));
    }


    @Autowired
    NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    @Test
    public void Test7(){
        // 使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值
        String sql = "insert into employee(`name`,`salary`)values(:name,:salary)";
        Map<String,Object> map = new HashMap<>();
        map.put("name","爱你一万年");
        map.put("salary",new BigDecimal("99999.00"));

        namedParameterJdbcTemplate.update(sql,map);
    }




    @Test
    public void MaxSalary(){
        //查询最大salary
        // 第一个参数是sql语句
        // 第二个参数是转换回去的类型
        String sql = "select max(salary) from employee";
        BigDecimal bigDecimal = jdbcTemplate.queryForObject(sql, BigDecimal.class);
        System.out.println(bigDecimal);
    }



    @Test
    public void selectOneList(){
        //查询salary>4000的数据库记录,封装为List集合返回
        /**
         * BeanPropertyRowMapper类负责将查询回来的每一行记录转换为一个具体的Bean对象 <br/>
         *
         * JdbcTemplate工具类跟DbUtils中的QueryRunner接近<br/>
         *  update() 都是执行insert,delete,update的sql语句<br/>
         *
         *  在JdbcTemplate中,由方法决定查询一条记录,还是多条记录<br/>
         *      queryforObject()查询一条记录<br/>
         *      query() 查询多条记录
         * 在DbUtils中,由ResultSetHandler实现类决定查询一条记录,还是多条记录<br/>
         *      一条记录是 BeanHandler() <br/>
         *      多条记录是 BeanListHandler()
         */
        String sql = "select `id`,`name` , `salary` from employee where salary > ?";
        List<Employee> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Employee>(Employee.class),new BigDecimal("4000.00"));
        for (Employee employee : list) {
            System.out.println(employee);
        }
    }



    @Test
    public void testSeleteOne(){

        /**
         *  实验4:查询id=5的数据库记录,封装为一个Java对象返回
         * queryForObject() 用于查询返回一行的sql <br/>
         *  第一个参数是sql语句<br/>
         *  第二个参数是RowMapper接口实现类。这个接口负责将查询回来的结果转换为需要的数据( 比如Employee对象 )<br/>
         *  第三个参数是sql语句中占位符的值
         *  BeanPropertyRowMapper 类似于Mybatis中的resultMap 进行映射
         */
        String sql = "select `id`,`name` , `salary` from employee where id = ?";
        Employee employee = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Employee>(Employee.class),5);
        System.out.println(employee);
    }

    @Test
    public void batchInsert(){
        //实验3:批量插入
        String sql = "insert into employee (`name`,`salary`) values (?,?)";
        List<Object[]> list = new ArrayList<>();
        list.add(new Object[]{"小白",new BigDecimal("12400.00")});
        list.add(new Object[]{"小小",new BigDecimal("12500.00")});
        list.add(new Object[]{"小六",new BigDecimal("12600.00")});
        jdbcTemplate.batchUpdate(sql,list);
    }


    @Test
    public void UserUpdate(){
        // 实验2:将id=5的记录的salary字段更新为1300.00
        String sql = "update employee set salary = ? where id = ?";
        jdbcTemplate.update(sql,new BigDecimal(1300.00),5);
    }



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值