文章目录

  • 1. 使用Java 的方式配置Spring
  • 2. 代理模式
  • 3. 动态代理 简述
  • 4. 动态代理的使用
    • 4.1 动态代理的使用
    • 4.2 动态代理补充
  • 5. Spring AOP
  • 6. 实现aop(一) 通过SpringAPI接口实现(围绕接口来实现)
  • 7. execution()方法参数含义
  • 8. 实现aop(二) 自定义类方式 (围绕自定义类,也就是切面(aspect)定义来实现)
  • 9. 实现aop(三) 使用注解来实现
  • 10. JDBC Template 概述 和 准备
  • 11. JDBC Template 的增删改查
  • 12. JdbcTemplate 的批量操作

1. 使用Java 的方式配置Spring


我们不完全使用Spring的xml来配置,我们使用Java代码的方式来操作。

JavaConfig是Spring的一个子项目,在Spring 4之后,他成为了一个核心功能!


通过 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 来获取容器context,对应的情况不同!

前者是通过Spring和xml方式来获取的,后者是通过部分Spring注解和Java代码获取的!

代码如下:

User.java代码(实体类):

package com.itholmes.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;//此时@Component注解的意思,就是说明这个类被Spring接管了,注册到容器中。
@Component
public class User {private String name;public String getName() {return name;}@Value("itholmes")//属性注入值,也可以在set方法上面。public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}
}

config层下的HolmesConfig.java配置类:

一定记住配置类中几个注解的使用!

package com.itholmes.config;import com.itholmes.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;//@Configuration注解也会被Spring容器托管,注册到容器中,因为它本身也包含了@Component注解。
//@Configuration代表这是一个配置类,就和我们之前的beans.xml文件是一样的。
@Configuration
@ComponentScan("com.itholmes.pojo")//同样也可以通过@ComponentScan,在这里进行一个扫描操作。
@Import(HolmesConfig2.class)//@Import注解,将相应的配置文件导入当前,也就是合并的效果。
public class HolmesConfig {//注册一个bean,就相当于我们之前写的一个bean标签。//该方法的名字getUser就是相当于bean标签中的id属性。//这个方法的返回值,就相当于bean标签中的class属性。@Beanpublic User getUser(){return new User();//就是返回值,要注入到bean中的对象。}}

模拟导入HolmesConifg配置类的配置类2:

package com.itholmes.config;import org.springframework.context.annotation.Configuration;@Configuration
public class HolmesConfig2 {}

测试类:

一定牢记测试类中的AnnotationConfigApplicationContext(HolmesConfig.class);作用!

/*概述:@Date:Create in 14:45 2021/12/30
*/import com.itholmes.config.HolmesConfig;
import com.itholmes.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class MyTest {public static void main(String[] args) {//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载。ApplicationContext context = new AnnotationConfigApplicationContext(HolmesConfig.class);User user = context.getBean("getUser", User.class);System.out.println(user.getName());}}

这种纯java的配置方式,在Spring Boot中随处可见。

2. 代理模式


Java的23种设计模式之一的代理模式,很重要,因为它是Spring AOP的底层内容。

代理模式的分类:

  • 静态代理。
  • 动态代理。

平时,我们学习中操作的都是静态代理模式,定义一个接口,一个用户,一个代理角色,一个厂家。用户通过代理来获取操作厂家提供资源的一个效果。


纵向开发 和 横向开发的效果图:

3. 动态代理 简述


简而言之,动态代理,在代理模式的情况下,它是自动生成代理类。

动态代理的描述:

  • 动态代理的底层都是通过反射来实现的。
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
    • 基于接口动态代理机制:JDK动态代理(也是默认的)。
    • 基于类的动态代理机制:cglib动态代理。
    • java字节码实现:Javassist。

Spring AOP是基于动态代理的,基于两种动态代理机制:JDK动态代理(也是默认的)和CGLIB动态代理。


需要了解两个类:Proxy (代理),InvocationHandler (调用处理程序)。

InvocationHandler是java.lang.reflect反射包下的一个接口:

Proxy 是java.lang.reflect反射包下的一个类:

proxy类对应的4个静态方法:

4. 动态代理的使用

4.1 动态代理的使用


Rent接口:

package com.itholmes.demo3;public interface Rent {void rent();
}

Host类(房东):

package com.itholmes.demo3;public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东要出租房子!");}}

ProxyInvocationHandler.java实现InvocationHandler接口的类,这个类可以自动生成代理类。

package com.itholmes.demo3;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//我们会用这个类自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {//被代理的接口private Rent rent;public void setRent(Rent rent) {this.rent = rent;}//生成得到代理类//第一个参数,类构造器:this.getClass().getClassLoader()加载到代理类在那个位置。//第二个参数,得到实现rent的接口:rent.getClass().getInterfaces()表示它要代理的接口是哪一个接口。//第三个参数,实现InvocationHandler的类,这里我们本身就实现了InvocationHandler了,所以用this就可,。public Object getProxy(){Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);//System.out.println("判断o:"+o);return o;}//上面的Proxy.newProxyInstance()方法执行后,会执行当前的invoke方法来处理代理实例,并返回结果。@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {seeHouse();//动态代理的本质,就是使用反射机制实现的!Object invoke = method.invoke(rent, args);//System.out.println("判断invoke:"+invoke);fare();return invoke;}//我们可以通过打印来判断这里的invoke对象和上面的o对象是一个对象么?//invoke:com.itholmes.demo3.Host@2b193f2d//getProxy:com.itholmes.demo3.Host@2b193f2d//返回结果不难看出就是一个对象。public void seeHouse(){System.out.println("中介带看房子");}public void fare(){System.out.println("中介收费");}
}

Client用户测试类:

package com.itholmes.demo3;public class Client {public static void main(String[] args) {//真实角色(房主)Host host = new Host();//代理角色(中介):现在没有ProxyInvocationHandler handler = new ProxyInvocationHandler();//通过调用程序处理角色(当前我们定义的ProxyInvocationHandler类)来处理我们要调用的接口对象。handler.setRent(host);Rent proxy = (Rent)handler.getProxy();//这里的proxy就是动态生成的!proxy.rent();}}

此外,invoke中的method方法可以调用很多方法,例如:
method.getName()获取名字等等。

4.2 动态代理补充


工厂模式和代理模式的区别?

  • 工厂模式用来生成一个对象东西的。代理模式用来增强一些功能的。

静态代理的缺点:接口写死了,代理人处理的成员对象变量写死了。


动态代理的远离实现就是通过反射完成的,反射的三要素是动态代理的核心!!


动态代理生成的代理类是代码运行时加载到内存的,不是我们提前定义的!!


如果我们见到$proxy 这样的样式,那就是动态代理生成的。

5. Spring AOP


面向对象程序设计(Object Oriented Programming , OOP)

面向切面编程:(Aspect Oriented Programming , AOP)

AOP是OOP的延续。


AOP的一个效果图如下:


SpringAOP中,通过Advice定义横切逻辑。

在Spring中支持5种类型的Advice:

6. 实现aop(一) 通过SpringAPI接口实现(围绕接口来实现)


实现AOP前,需要一个织入依赖包aspectjweaver!

导入完包后,要导入响应的约束和支持约束条件:

其实不管什么约束条件都是差不多的格式,稍微改改字母就能修改。

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"

上面准备工作完成后,我们创建两个类分别实现了AfterReturningAdvice 和 MethodBeforeAdvice接口:

log类实现MethodBeforeAdvice方法执行前调用它:

package com.itholmes.log;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class Log implements MethodBeforeAdvice{//before方法的参数://method:要执行的目标对象的方法//objects:参数//o:目标对象@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");}
}

AfterLog类,调用AfterReturningAdvice接口,负责执行方法执行后的内容:

package com.itholmes.log;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class AfterLog implements AfterReturningAdvice {//returnValue:使用AfterReturningAdvice是可以拿到一个returnValue返回值的。//其他的参数和BeforeAdvice中的before参数一样。@Overridepublic void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("执行了"+method.getName()+"方法,返回结构为:"+returnValue);}
}

UserService接口:

package com.itholmes.service;public interface UserService {public void add();public void delete();public void update();public void select();
}

UserServiceImpl实现类:

package com.itholmes.service;public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void delete() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("更新了一个用户");}@Overridepublic void select() {System.out.println("查询了一个用户");}
}

再往后,先在xml文件中,注册bean,然后通过xml方式来指定aop的相关内容了。
创建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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.itholmes.service.UserServiceImpl"/><bean id="log" class="com.itholmes.log.Log"/><bean id="afterLog" class="com.itholmes.log.AfterLog"/><!--上面的AOP约束一定要导入!--><!--配置AOP:需要导入aop的约束--><!--方式一:使用原生的Spring API接口--><aop:config><!--切入点: expression:表达式 , execution(要执行的位置! * * * *) *在这代表的是所有的意思。--><!--execution()方法参数含义下面会说到!--><aop:pointcut id="pointcut" expression="execution(* com.itholmes.service.UserServiceImpl.*(..))"></aop:pointcut><!--执行环绕增加--><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config></beans>

最后,我们测试一下mytest类:

import com.itholmes.service.UserService;
import com.itholmes.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");//注意:AOP实现原理是动态代理,而动态代理代理的是接口,因此在这我们只能写接口类型。UserService userService = (UserService) context.getBean("userService");userService.add();}
}

7. execution()方法参数含义


先说一下execution()方法参数的含义。

execution()是最常用的切点函数,其语法如下所示:

整个表达式可以分为五个部分:

  • 1. execution(): 表达式主体。
  • 2. 第一个:修饰符,一般省略,*代表任意。可以省略。
  • 3. 第二个*号:表示返回类型,*号表示所有的类型。不能省略
  • 3. 第三个:包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。可以省略。
  • 4. 第四个*号:表示类名,*号表示所有的类。可以省略。
  • 5. 第五个:*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。这里为了是防止重载的!!!不能省略。

例如:

execution(void,com.itholmes.service.className(int,String));

提示一下,void是有返回值的,但是我们平时什么不返回,所以可以使用return; 因此上面在execution()中的第一个*号位置也可以填写void。

构造方法是没有返回值的不需要使用void,因此我们平时的构造函数没有void。

这些参数理解了才更容易理解AOP。

8. 实现aop(二) 自定义类方式 (围绕自定义类,也就是切面(aspect)定义来实现)


测试类,接口,接口实现类不变。

首先,创建一个自定义类:

package com.itholmes.diy;public class DiyPointCut {public void before(){System.out.println("------方法执行前-------");}public void after(){System.out.println("-------方法执行后--------");}}

xml配置文件来进行配置:
其实就是换了aop:aspect来操作而已:

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.itholmes.service.UserServiceImpl"/><bean id="log" class="com.itholmes.log.Log"/><bean id="afterLog" class="com.itholmes.log.AfterLog"/><!--方式二:通过自定义类方式实现--><bean id="diy" class="com.itholmes.diy.DiyPointCut"/><aop:config><!--自定义切面: ref指定要引用的类--><aop:aspect ref="diy"><!--同样,也是要切入点:--><aop:pointcut id="point" expression="execution(* com.itholmes.service.UserServiceImpl.*(..))"/><!--通知,method指定方法,pointcut-ref指定在切入点。--><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config></beans>

9. 实现aop(三) 使用注解来实现


接口,实现类,测试类不变。

设置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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.itholmes.service.UserServiceImpl"/><bean id="log" class="com.itholmes.log.Log"/><bean id="afterLog" class="com.itholmes.log.AfterLog"/><!--方式三:使用注解来实现AOP--><bean id="annotationPointCut" class="com.itholmes.diy.AnnotationPointCut"/><!--开启注解支持--><!--JDK动态代理机制(默认的,就是proxy-target-class="false") , cglib动态代理相反(也就是proxy-target-class="true")。--><aop:aspectj-autoproxy proxy-target-class="false"/><!--autoproxy自动代理--></beans>

定义一个AnnotationPointCut,在里面设置注解信息。

package com.itholmes.diy;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;//方式三:使用注解来实现AOP方式//标注:这个类是一个切面
@Aspect
public class AnnotationPointCut {//这里要注意一下,在junit中也有一个@Before注解,不要导错了。@Before("execution(* com.itholmes.service.UserServiceImpl.*(..))")public void before(){System.out.println("--------方法执行前");}//同样不要到错包。@After("execution(* com.itholmes.service.UserServiceImpl.*(..))")public void after(){System.out.println("--------方法执行后");}//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点。//joinPoint就是效果图中的连接点@Around("execution(* com.itholmes.service.UserServiceImpl.*(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕前");Signature signature = joinPoint.getSignature();//获得签名//System.out.println("signature:"+signature);//执行方法Object proceed = joinPoint.proceed();System.out.println("环绕后");}//注意这个执行顺序,执行谁后执行谁!//环绕前//--------方法执行前//增加了一个用户//环绕后//--------方法执行后}

三种实现AOP效果都一样,后两者简便一些。

10. JDBC Template 概述 和 准备


Spring整体效果图如下,而JDBC Template是属于蓝色部分的内容:

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


第一步,导入jar包:

首先,引入jar包:(该用maven依赖的依赖,不会maven该导包的导包。)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spring5_atguigu_demo05</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--spring-webmvc基本上包含了spring核心的所有jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.13</version></dependency><!--mysql驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.22</version></dependency><!--阿里巴巴的德鲁伊jar包--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.9</version></dependency><!--spring的jdbcjar包。--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.6.RELEASE</version></dependency><!--spring tx 不知道干啥的。--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.6.RELEASE</version></dependency><!--spring orm 不知道干啥的--><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>5.2.6.RELEASE</version></dependency></dependencies>
</project>

第二步,在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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--组件扫描--><context:component-scan base-package="com.itholmes.spring5.*"/><!--数据库池的4个配置信息:--><!--destroy-method="close" 的作用就是当数据库连接不使用时,将连接重新放入连接池,不销毁,可以方便下一次的使用。注意,这里的driverClassName,平时我们连接数据库直接写的driver,不要搞混。--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/emp?ServerTimezone=Aisa/shanghai"/><property name="username" value="root"/><property name="password" value="0818"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/></bean></beans>

第三步,创建对应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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--组件扫描--><context:component-scan base-package="com.itholmes.spring5.*"/><!--数据库池的4个配置信息:--><!--destroy-method="close" 的作用就是当数据库连接不使用时,将连接重新放入连接池,不销毁,可以方便下一次的使用。注意,这里的driverClassName,平时我们连接数据库直接写的driver,不要搞混。--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/emp?ServerTimezone=Aisa/shanghai"/><property name="username" value="root"/><property name="password" value="0818"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/></bean><!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--这里必须用set注入,不能用构造器,因为他源码本质上是setDataSource方法。--><property name="dataSource" ref="dataSource"/></bean><bean id="bookService" class="com.itholmes.spring5.service.BookService"/>
</beans>

第四步,创建service类,创建dao类,在dao注入jdbcTemplate对象(算是实操):

在beans.xml配置文件中添加组件扫描:

<!--组件扫描-->
<context:component-scan base-package="com.itholmes.spring5"/>

测试类Test:

/*概述:@Date:Create in 15:32 2021/12/31
*/import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestBook {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");BookService service = context.getBean("bookService", BookService.class);Book book = new Book();book.setBook_name("张三");book.setBook_password("zhangsan");service.addBook(book);}}

11. JDBC Template 的增删改查


增删改的操作,都是调用jdbcTemplate对象中的update方法,主要的查询有多种不同的返回值和方式!

bean的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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--组件扫描--><context:component-scan base-package="com.itholmes.spring5.*"/><!--数据库池的4个配置信息:--><!--destroy-method="close" 的作用就是当数据库连接不使用时,将连接重新放入连接池,不销毁,可以方便下一次的使用。--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/emp?ServerTimezone=Aisa/shanghai"/><property name="username" value="root"/><property name="password" value="0818"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/></bean><!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--这里必须用set注入,不能用构造器,因为他源码本质上是setDataSource方法。--><property name="dataSource" ref="dataSource"/></bean></beans>

Book实体类:

package com.itholmes.spring5.bean;public class Book {private int user_id;private String user_name;private String user_password;public int getUser_id() {return user_id;}public void setUser_id(int user_id) {this.user_id = user_id;}public String getUser_name() {return user_name;}public void setUser_name(String user_name) {this.user_name = user_name;}public String getUser_password() {return user_password;}public void setUser_password(String user_password) {this.user_password = user_password;}@Overridepublic String toString() {return "Book{" +"user_id=" + user_id +", user_name='" + user_name + '\'' +", user_password='" + user_password + '\'' +'}';}
}

BookDao层的接口:

package com.itholmes.spring5.dao;import com.itholmes.spring5.bean.Book;import java.util.List;public interface BookDao {public void add(Book book);public void update(Book book);public void delete(String id);public int selectCount();public Book findBookInfo(String id);public List<Book> findBookList();
}

实现BookDao接口的实现类(重点,多看查询操作是怎么完成的):

package com.itholmes.spring5.dao;import com.itholmes.spring5.bean.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
public class BookDaoImpl implements BookDao{//注入jdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;//添加操作@Overridepublic void add(Book book) {String sql = "insert into `user` (`user_name`,`user_password`)values(?,?)";//重点:jdbcTemplate中可以通过update方法来实现添加操作。//update方法有两个参数://第一个参数:String sql 是sql语句//第二个参数:Object... args(可变参数,也可以添加数组!) 是sql语句我们需要传入?参数,这个就是我们要传入的不同类型的值。//int update = jdbcTemplate.update(sql, book.getBook_name(), book.getBook_password());//因为args是一个可变参数,我们也可以添加个数组啥的。Object[] args = {book.getUser_name(), book.getUser_password()};int update = jdbcTemplate.update(sql, args);System.out.println(update);}//修改方法@Overridepublic void update(Book book) {String sql = "update `user` set user_name=?,user_password=? where user_id=?";Object[] args = {book.getUser_name(),book.getUser_password(),book.getUser_id()};int update = jdbcTemplate.update(sql, args);System.out.println(update);}//删除方法@Overridepublic void delete(String id) {String sql = "delete from `user` where user_id=?";int update = jdbcTemplate.update(sql, id);System.out.println(update);}//查询表中记录数(返回某个值)@Overridepublic int selectCount() {String sql = "select count(*) from `user`";//查询操作和上面的增删改不同,它分为很多不同的方法,要牢记!!!Integer query = jdbcTemplate.queryForObject(sql, Integer.class);return query;}//查询表中数据,进而返回一个对象(返回对象)@Overridepublic Book findBookInfo(String id) {String sql = "select * from `user` where user_id=?";//下面调用的是和上面重载类型差不多的方法,多了一个参数rowMapper参数。//rowMapper是一个接口,返回不同类型数据,使用这个接口里面的实现类完成数据的封装。Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);return book;}//查询表中的多个数据,进而返回一个集合(返回集合)@Overridepublic List<Book> findBookList() {String sql = "select * from `user`";//同样和上面相同也是有三个参数,返回结果为集合,只不过这里第三个参数给sql传递值,就是sql里面的?,没有所以省略就好。List query = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Book.class));return query;}}

service层的BookService类:

package com.itholmes.spring5.service;import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class BookService {//注入dao@Autowiredprivate BookDao bookDao;//添加方法public void addBook(Book book){bookDao.add(book);}//修改方法public void updateBook(Book book){bookDao.update(book);}//删除方法public void deleteBook(String id){bookDao.delete(id);}//查询表中记录数(返回某个值)public int selectBookCount(){int i = bookDao.selectCount();return i;}//查询数据库中的某个对象(返回某个对象)public Book selectBook(String id){return bookDao.findBookInfo(id);}//查询数据库中的多个数据(返回集合)public List<Book> selectBookList(){return bookDao.findBookList();}
}

测试类Test类:

/*概述:@Date:Create in 15:32 2021/12/31
*/import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.Iterator;
import java.util.List;public class TestBook {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");BookService service = context.getBean("bookService", BookService.class);//1.测试增加//Book book = new Book();//book.setUser_name("张三");//book.setUser_password("zhangsan");//service.addBook(book);//2.测试修改//Book book2 = new Book();//book2.setUser_id(1);//book2.setUser_name("itholmes");//book2.setUser_password("456");//service.updateBook(book2);//3.测试删除//service.deleteBook("2");//查询分为3种:返回某个值,返回某个对象,返回某个集合。//4.测试查询count(*)数量int i = service.selectBookCount();System.out.println(i);//5.测试返回得到book对象类型//注意返回对象的属性值,必须与数据库的字段值对应起来,不然得不到数据!!Book book = service.selectBook("1");System.out.println(book.toString());//6.测试返回得到集合类型List<Book> books = service.selectBookList();System.out.println("------------");System.out.println(books);//这里可以直接打印System.out.println("------------");//遍历方式一:迭代器遍历Iterator<Book> iterator = books.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}System.out.println("------------");//遍历方式二:强化for循环for (Book b : books){System.out.println(b);}}
}

12. JdbcTemplate 的批量操作


批量修改,删除,添加都是,使用的jdbcTempate中的batchUpdate方法:

该方法有两个参数:

  • 参数一:sql语句。
  • 参数二:List集合,添加多条记录数据。

仅仅举一个添加操作,都是一样的:

//批量添加
public void batchAddBook(List<Object[]> batchArgs){String sql = "insert into `user` (`user_name`,`user_password`)values(?,?)";//batchUpdate方法将list集合中的内容,批量插入数据库中int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);System.out.println(Arrays.toString(ints));
}

同样,我们测试一下:


import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class TestBook {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");BookService service = context.getBean("bookService", BookService.class);//注意List<Object[]>的用法:Object[] o1 = {"李四","zxc"};Object[] o2 = {"李五","zxc"};Object[] o3 = {"李六","zxc"};List<Object[]> batchArgs = new ArrayList<>();batchArgs.add(o1);batchArgs.add(o2);batchArgs.add(o3);service.batchAdd(batchArgs);}}

Spring5框架 笔记总结(二)相关推荐

  1. java具名参数_Spring框架笔记(二十五)——NamedParameterJdbcTemplate与具名参数

    在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定. 在 Spring JDBC 框架中, 绑定 ...

  2. Spring框架笔记(二十二)——切点表达式的重用

    2019独角兽企业重金招聘Python工程师标准>>> 在编写 AspectJ 切面时, 可以直接在通知注解中书写切入点表达式. 但同一个切点表达式可能会在多个通知中重复出现. 在 ...

  3. nrf52832 学习笔记(二)SDK框架分析

    nrf52832 学习笔记(二)SDK框架分析 个人对SDK框架的一些理解,如有错误欢迎斧正. flash 分区 在不包含DFU的情况下,nrf52832 flash划分为: MBR 0x000000 ...

  4. ET6.0服务器框架学习笔记(二、一条登录协议)

    ET6.0服务器框架学习笔记(二.一条登录协议) 上一篇主要记录ET6.0的服务器启动功能,本篇主要记录ET6.0完整的一条协议,从配置到生成协议数据,到从客户端发送给服务端,再发送回客户端的流程 文 ...

  5. 尚硅谷-Spring5课堂笔记

    文章目录 Spring5框架 Spring-IOC IOC容器-Bean管理(基于xml方式) IOC容器-Bean管理(基于xml方式)② IOC容器-Bean管理(基于注解方式) Spring-A ...

  6. OpenCV学习笔记(二十一)——绘图函数core OpenCV学习笔记(二十二)——粒子滤波跟踪方法 OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt OpenCV学习笔记(二十

    OpenCV学习笔记(二十一)--绘图函数core 在图像中,我们经常想要在图像中做一些标识记号,这就需要绘图函数.OpenCV虽然没有太优秀的GUI,但在绘图方面还是做得很完整的.这里就介绍一下相关 ...

  7. ET框架笔记 (笑览世界写)(转)

    客户端 1.使用unity2017.2.0版本及以上2018版以下,编译原始版ET客户端报没有引用错误时,删除hoxfit下引用的UnityEngine.dll和UnityEngine.UI.dll, ...

  8. 《C++标准程序库》笔记之二

    <C++标准程序库>笔记之二 本篇博客笔记顺序大体按照<C++标准程序库(第1版)>各章节顺序编排. ------------------------------------- ...

  9. Java总结:Spring5框架(1)

    Spring5框架(1) 一:什么是Spring? Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用 ...

最新文章

  1. 博士生在没有导师指导的情况下,该如何自己选题发 CVPR ?
  2. Centos7如何轻松配置yum国内源
  3. android文字广告的循环滚动,android怎样写一个循环文字滚动的TextView
  4. python画三维几何图-Python常见几何图形绘制
  5. 034_jdbc-mysql-C3P0
  6. MOSS2007 无法上传超过30M或者50M的大文件解决办法 (转)
  7. Redis的session管理和Memcached的session管理不同
  8. Idea更改console控制台 日志颜色(非插件)
  9. php curl json post请求_php post请求发送json对象数据参数
  10. 如何从初级程序员变成高级程序员?赶紧看一看
  11. 12bit的图像如何向8bit转化_干货分享 | 如何鉴别Western Blot图像的真实性?
  12. Java练习 SDUT-3338_计算各种图形的周长(接口与多态)
  13. 如何让微博营销更具效力
  14. java修改excel图表数据源,导出excel图表文件
  15. 怎么注册Github?用手机2分钟完成注册,互联网就是互相连接
  16. 联合舰队的覆灭(7)
  17. android手机改电视,DIY让手机变成万能电视遥控器 手机万能遥控器设置方法
  18. 【端午趣味征文】有vcs和python吗?来,我教你在波形里画个粽子!
  19. 传感器课程实验:传感器静态特性研究-应变式传感器
  20. AC算法的高效C++实现

热门文章

  1. BAT中读取文本文件
  2. Silverlight游戏设计(Game Design):(十)梦幻西游(Demo) 之 “天人合一”①
  3. 苹果6严重卡顿_iOS 双开助手来啦!不是切换账号,上架了苹果官方应用平台!...
  4. div+css静态网页设计——千与千寻-电影图文(9页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计
  5. 计算机软件测试实训,软件测试实训报告.doc
  6. 红外测距传感器(GP2D12、74HC595、ADC0832)
  7. matlab如何将三维转为二维_求助,二维图像如何绕轴旋转成为三维图像
  8. 应力中的APDL命令流
  9. Vivaldi浏览器登陆Linux设备
  10. python三门问题_python模拟“三门问题”