spring动态代理 AOP JdbcTemplate spring整合mybatis

002-Spring注解和AOP实现

一、知识点回顾

spring环境搭建步骤
spring中scope作用域有哪些
自动装配的方式

二、本章任务

完成IOC方式使用
完成动态代理
完成AOP注解使用
完成AOP xml使用

三、知识点

1、IOC注解

Spring框架中有注解和XML两种配置方式,包括Spring中的IOC和AOP也一样,都有XML和注解两种方式两种方式各有千秋。

1.1、xml和注解的区别

1.1.1 XML配置
优点有:
XML配置方式进一步降低了耦合,使得应用更加容易扩展,即使对配置文件进一步修改也
不需要工程进行修改和重新编译。
在处理大的业务量的时候,用XML配置应该更加好一些。因为XML更加清晰的表明了各个
对象之间的关系,各个业务类之间的调用。同时spring的相关配置也能一目了然。
缺点有:
配置文件读取和解析需要花费一定的时间,配置文件过多的时候难以管理,无法对配置的正
确性进行校验,增加了测试难度。
1.1.2 annotation配置
优点有:
在class文件中,可以降低维护成本,annotation的配置机制很明显简单
不需要第三方的解析工具,利用java反射技术就可以完成任务
编译期可以验证正确性,查错变得容易
提高开发效率
缺点有:
如果需要对于annotation进行修改,那么要重新编译整个工程
业务类之间的关系不如XML配置那样容易把握。
如果在程序中annotation比较多,直接影响代码质量,对于代码的简洁度有一定的影响
Spring 的IOC 的XML方式我们已经掌握的差不多了,下面来学习学习注解的方式

1.2 注解注入使用步骤

1.2.1 Autowired

1.2.1.1 创建项目并导包

     和昨天的步骤一样,不过需要引入一个新的jar包

spring-aop-4.2.1.RELEASE.jar

1.2.1.3 开启注解的支持

<?xml version="1.0" encoding="UTF-8"?>




<context:annotation-config />

1.2.1.2 业务类
业务类内容不变,只是要多加几个注解
public class UserService {
private IUserDao userDao;

@Autowired
public void setUserDao(IUserDao userDao) {
    this.userDao = userDao;
}

}
1.2.1.3 知识点
@Autowired(自动封装)
该注解可以加在set方法上或者直接加在属性上,如果写在setter方法上,就会通过setter方法进行注入,如果写在变量上,就直接通过反射设置变量的值,不经过setter方法。
注入时,会从spring容器中,找到一个和这个属性数据类型匹配的实例化对象注入进来,默认使用byType,根据类型匹配。
如果只能找到一个这个数据类型的对象的时候,就直接注入该对象。
如果找到了多个同一个类型的对象的时候,就会自动更改为byName来进行匹配,根据set方法对应的参数列表的局部变量名来匹配。
如:
private IUserDao userDao;
@Autowired
public void setUserDao(IUserDao userDao){};
会先找符合IUserDao类型的对象有多少,一个的话就直接拿过来
多个的话,就按照setUserDao方法的参数列表的局部变量名来找
找不到就报错
@Autowired(required=false) 就说明 这个值可以为null,如果Spring容器中没有对应的对象,不会报错
默认为true,比如beans.xml中没有创建dao对象,就会报错,加上required=false就不会报错
@Qualifier :
以指定名字进行匹配

private IUserDao userDao;
@Autowired
public void setUserDao(@Qualifier(“userDao2”)IUserDao userDao){};
这时候就不会按照userDao来进行匹配了,而是强制使用userDao2来进行比配,也就不会按照类型匹配了

1.2.1.4 配置文件
注意增加xml解析器内容,即头部beans内容

<?xml version="1.0" encoding="UTF-8"?>




<context:annotation-config />









1.2.1.5 测试
@Test
public void testAdd() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
“beans.xml”);
// userService是bean的id或name
UserService userService = (UserService) applicationContext
.getBean(“userService”);
System.out.println(userService.getUserDao());
}

因为创建了两个对象,所以Dao构造方法执行两次
由于代码中定义了根据name匹配,所以最终找到的是daoId=2的对象

1.2.2 Resource
Resource这个注解是javaEE的,在javax包下,所以不需要导入其他jar包
@Resource默认使用byName的方式,按照名字匹配,可以写在setter方法上也可以写在变量上
先匹配set方法的名字,匹配不上再匹配方法参数列表的名字
如果还是匹配不上就会转换为byType,根据类型匹配
当然我们也可以指定名字
@Resource(name=”userDao”)
就相当于 Autowired和Qualifier 一起使用
相关的还有一个 @Inject 根据type匹配,通过named指定名字,自行学习

1.2.2.1 业务类
@Resource(name=“userDao”)
public void setUserDao(UserDao userDao) {
System.out.println(“--------------”);
this.userDao2 = userDao;
}

1.2.2.2 测试
@Test
public void testAdd() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
“beans.xml”);
UserService userService = (UserService) applicationContext
.getBean(“userService”);
System.out.println(userService.getUserDao());
}

1.3 注解实例化使用步骤
上面的两个注解是用来进行注入对象的,实例化对象也有对应的注解,先来个简单示例进行了解
1.3.1 配置文件
创建项目和导包和上面的一样,业务类也一致,可以复制过来进行更改
在配置文件中设置使用注解形式实例化对象 只需要加入
<context:component-scan base-package=“com.tledu” />

<?xml version="1.0" encoding="UTF-8"?>



<context:annotation-config />

<context:component-scan base-package=“com.tledu” />

1.3.2 业务类
所有需要实例化对象的类上面都加上@Component
默认是以类名首字母小写作为名字进行存储
可以使用@Component(“xxx”) 或者@Component(value=”xxx”)来设置名字
以上这三种写法都可以
@Component(value=“userDao”)
public class UserDaoImpl implements UserDao {
@Component
public class User {
@Component(“userService”)
public class UserService {

1.3.3 测试
@Test
public void testAdd() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
“beans.xml”);
// userService是value设置的值或者是类名首字母小写
UserService userService = (UserService) applicationContext
.getBean(“userService”);
System.out.println(userService.getUserDao());
}

1.3.4 注解分类
像上面我们写的代码中,所有实例化对象都是要的是@Component 这样不是很好,官方给出了几个分类
@Controller :WEB 层 ,就是和页面交互的类
@Service :业务层 ,主要处理逻辑
@Repository :持久层 ,就是Dao操作数据库
这三个注解是为了让标注类本身的用途清晰,Spring 在后续版本会对其增强
@Component: 最普通的组件,可以被注入到spring容器进行管理
@Value :用于注入普通类型. 可以写在变量上和setter方法上
@Autowired :自动装配,上面描述比较详细,可以参照上面
@Qualifier:强制使用名称注入.
@Resource 相当于: @Autowired 和@Qualifier 一起使用
@Scope: 设置对象在spring容器中的生命周期
取值 :
singleton:单例
prototype:多例
@PostConstruct :相当于 init-method
@PreDestroy :相当于 destroy-method

1.3.5 注解区别
引用spring的官方文档中的一段描述:
在Spring2.0之前的版本中,@Repository注解可以标记在任何的类上,用来表明该类是用来执行与数据库相关的操作(即dao对象),并支持自动处理数据库操作产生的异常
在Spring2.5版本中,引入了更多的Spring类注解:@Component,@Service,@Controller。@Component是一个通用的Spring容器管理的单例bean组件。而@Repository, @Service, @Controller就是针对不同的使用场景所采取的特定功能化的注解组件。
因此,当你的一个类被@Component所注解,那么就意味着同样可以用@Repository, @Service, @Controller来替代它,同时这些注解会具备有更多的功能,而且功能各异。
最后,如果你不知道要在项目的业务层采用@Service还是@Component注解。那么,@Service是一个更好的选择。
就如上文所说的,@Repository早已被支持了在你的持久层作为一个标记可以去自动处理数据库操作产生的异常(译 者注:因为原生的java操作数据库所产生的异常只定义了几种,但是产生数据库异常的原因却有很多种,这样对于数据库操作的报错排查造成了一定的影响;而 Spring拓展了原生的持久层异常,针对不同的产生原因有了更多的异常进行描述。所以,在注解了@Repository的类上如果数据库操作中抛出了异常,就能对其进行处理,转而抛出的是翻译后的spring专属数据库异常,方便我们对异常进行排查处理)。
注解 含义
@Component 最普通的组件,可以被注入到spring容器进行管理
@Repository 作用于持久层
@Service 作用于业务逻辑层
@Controller 作用于表现层(spring-mvc的注解)

1.4 新注解

1.4.1、Configuration
作用: 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要
使用AnnotationApplicationContext(有@Configuration 注解的类.class)。
属性: value:用于指定配置类的字节码

package com.tledu.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfiguration {

}
注意:
我们已经把配置文件用类来代替了,但是如何配置创建容器时要扫描的包呢?请看下一个注解。

1.4.2、ComponentScan
作用: 用于指定 spring 在初始化容器时要扫描的包。
作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package=“com.tledu”/>是一样的。
属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。

@Configuration
@ComponentScan(“com.tledu.spring”)
public class SpringConfiguration {

}

注意: 我们已经配置好了要扫描的包,但是数据源和 JdbcTemplate 对象如何从配置文件中移除呢? 请看下一个注解。

1.4.3、Bean

作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性: name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。

package com.tledu.zrz.config;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
public class JdbcConfig {
/**

  • 创建一个数据源,并存入 spring 容器中
  • @return
    */
    @Bean(name = “dataSource”)
    public BasicDataSource createDataSource() {
    try {
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName(“com.mysql.jdbc.Driver”);
    bds.setUrl(“jdbc:mysql://localhost:3306/ssm”);
    bds.setUsername(“root”);
    bds.setPassword(“root”);
    return bds;
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    }

注意:
由于没有配置文件,创建数据源的配置又都写死在类中了。如何把它们配置出来呢?
请看下一个注解。

1.4.4 PropertySource

作用: 用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性: value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath

package com.tledu.config;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
public class JdbcConfig {
@Value(“ j d b c . d r i v e r " ) p r i v a t e S t r i n g d r i v e r ; @ V a l u e ( " {jdbc.driver}") private String driver; @Value(" jdbc.driver")privateStringdriver;@Value("{jdbc.url}”)
private String url;
@Value(“ j d b c . u s e r n a m e " ) p r i v a t e S t r i n g u s e r n a m e ; @ V a l u e ( " {jdbc.username}") private String username; @Value(" jdbc.username")privateStringusername;@Value("{jdbc.password}”)
private String password;
/**

  • 创建一个数据源,并存入 spring 容器中
  • @return
    */
    @Bean(name = “dataSource”)
    public BasicDataSource createDataSource() {
    try {
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName(driver);
    bds.setUrl(url);
    bds.setUsername(username);
    bds.setPassword(password);
    return bds;
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    }

jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

注意:
此时我们已经有了两个配置类,但是他们还没有关系。如何建立他们的关系呢?
请看下一个注解。

1.4.5 Import
作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
属性: value[]:用于指定其他配置类的字节码。

@Configuration
@ComponentScan(“com.tledu.spring”)
@Import({ JdbcConfig.class})
public class SpringConfiguration {

@Configuration
@PropertySource(“classpath:jdbc.properties”)
public class JdbcConfig {


2、AOP(面向切面编程)

Spring 是解决实际开发中的一些问题,而 AOP 解决 OOP 中遇到的一些问题.是 OOP 的延续和扩展.
使用面向对象编程 ( OOP )有一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志、安全检测等,我们只有在每个对象里引用公共行为,这样程序中就产生了大量的重复代码,程序就不便于维护了,所以就有了一个对面向对象编程的补充,即面向方面编程 ( AOP ), AOP 所关注的方向是横向的,区别于 OOP 的纵向。

2.1 为什么学习 AOP

在不修改源码的情况下,对程序进行增强
AOP 可以进行权限校验,日志记录,性能监控,事务控制

2.2 Spring 的 AOP 的由来

AOP 最早由 AOP 联盟的组织提出的,制定了一套规范.Spring 将 AOP 思想引入到框架中,必须遵守 AOP 联盟 的规范.

2.3 底层实现

AOP依赖于IOC来实现,在AOP中,使用一个代理类来包装目标类,在代理类中拦截目标类的方法执行并织入辅助功能。在Spring容器启动时,创建代理类bean替代目标类注册到IOC中,从而在应用代码中注入的目标类实例其实是目标类对应的代理类的实例,即使用AOP处理目标类生成的代理类。
代理机制:
Spring 的 AOP 的底层用到两种代理机制:
JDK 的动态代理 :针对实现了接口的类产生代理.
Cglib 的动态代理 :针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类的子类对象.

2.4动态代理
package com.tledu.dao.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxy implements InvocationHandler {
private Object obj;
public DynamicProxy(Object obj){
this.obj = obj;
}

/**
 * @param proxy  代理的对象
 * @param method 代理的方法
 * @param args   方法的参数
 * @return 方法的返回值
 * @throws Throwable 异常
 */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //前置操作
    before(method);
    method.invoke(obj,args);
    //后置操作
    after(method);
    return null;
}

private void before(Method method) {
    System.out.println(method.getName()+" 开始调用");
}
private void after(Method method) {
    System.out.println(method.getName()+" 调用结束");
}

}

测试
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
/**
第一个参数: 真实对象的类解析器
第二个参数: 实现的接口数组
第三个参数: 调用代理方法的时候,会将方法分配给该参数
*/
IUserDao iu = (IUserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),new DynamicProxy(userDao));
User u = new User();
u.setId(3);
u.setName(“aaa”);
iu.add(u);
}
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
InvocationHandler: 传入要代理的对象创建一个代理,动态代理方法在执行时,会调用创建代理类里面的invoke方法去执行
注意:
JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。
2.5 AOP相关术语

Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为
spring 只支持方法类型的连接点.
Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置
通知,后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行
期为类 动态地添加一些方法或 Field.
Target(目标对象): 代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程,spring 采用动态代理
织入,而 AspectJ 采用编译期织入和类装在期织入
Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合

2.6 注解方式

2.6.1 引入jar包

还是之前IOC的 再次引入三个就行,因为Spring的AOP是基于AspectJ开发的

2.6.2 配置文件
引入AOP约束,通过配置文件

<?xml version="1.0" encoding="UTF-8"?>




<context:annotation-config />
<context:component-scan base-package=“com.tledu” />

<aop:aspectj-autoproxy />

2.通过注解的方式开启切面支持 @EnableAspectJAutoProxy

2.6.3 AOP类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogInterceptor {
@Pointcut(“execution(public * com.tledu.service…*.add(…))”)
public void myMethod() {
// 假设这个方法就是被代理的方法
}
@Before(“myMethod()”)
public void beforeMethod() {
System.out.println(" execute start");
}
@After(“myMethod()”)
public void afterMethod() {
System.out.println(" execute end");
}
// 环绕,之前和之后都有,相当于 @Before 和 @After 一起使用
@Around(“myMethod()”)
public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
// @Around也可以和@Before 和 @After 一起使用
System.out.println(“around start”);
// 调用被代理的方法
pjp.proceed();
System.out.println(“around end”);
}
}

2.7 XML方式

2.7.1 引入jar包

和注解方式引入的一样

context:annotation-config/
<context:component-scan base-package=“com.tledu”/>

<bean id="logInterceptor" class="com.tledu.aop.LogInterceptor"></bean>
<aop:config>
    <aop:aspect id="logAspet" ref="logInterceptor">
        <!-- 需要进行代理的方法 -->
        <aop:pointcut expression="execution(public * com.tledu.service..*.add(..))"
                      id="pointcut" />
        <!-- 前后执行 -->
        <aop:before method="beforeMethod" pointcut-ref="pointcut" />
        <!-- 或者这样写,这样就不需要pointcut标签了 -->
        <!-- <aop:before method="before" pointcut="execution(public * com.tledu.service..*.add(..))"
      /> -->
        <aop:after method="afterMethod" pointcut-ref="pointcut" />
        <!-- 环绕,一般要么使用 around 要和使用 before和after 不会一起使用 -->
        <aop:around method="aroundMethod" pointcut-ref="pointcut" />
    </aop:aspect>
</aop:config>
2.6.3 AOP类 和注解一样,就是把注解去掉了 import org.aspectj.lang.ProceedingJoinPoint; public class LogInterceptor { public void myMethod() { // 假设这个方法就是被代理的方法 } public void before() { System.out.println(" execute start"); } public void after() { System.out.println(" execute end"); } // 环绕,之前和之后都有,相当于 @Before 和 @After 一起使用 public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable { // @Around也可以和@Before 和 @After 一起使用 System.out.println("around start"); // 调用被代理的方法 pjp.proceed(); System.out.println("around end"); } } 2.6.4 测试类 public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); UserService userService = context.getBean(UserService.class); User u = new User(); u.setName("李四"); userService.add(u); }

AOP其他知识点:http://www.blogjava.net/supercrsky/articles/174368.html

003-Spring整合JdbcTemplate及Mybatis

一、知识点回顾

Spring的常用注解有哪些
AOP是什么?能够解决什么问题
在Spring中如何使用AOP

二、本章任务

Spring中JdbcTemplate的使用
Spring整合Mybatis

三、知识点

1、jdbcTemplate

1.1、概述

它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。
操作关系型数据的:
JdbcTemplate
HibernateTemplate
操作 nosql 数据库的:
RedisTemplate
操作消息队列的:
JmsTemplate
我们今天的主角在 spring-jdbc.jar 中,我们在导包的时候,除了要导入这个 jar 包 外,还需要导入一个 spring-tx.jar(它是和事务相关的)。

1.2、jdbcTemplate对象创建
我们可以参考它的源码,来一探究竟:
public JdbcTemplate() {
}
public JdbcTemplate(DataSource dataSource) {
setDataSource(dataSource);
afterPropertiesSet();
}
public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
setDataSource(dataSource);
setLazyInit(lazyInit);
afterPropertiesSet();
}
 
除了默认构造函数之外,都需要提供一个数据源。既然有set方法,依据我们之前学过的依赖注入,我们可以在配置文件中配置这些对象

1.3、配置数据源
1.3.1、环境搭建

1.3.2、配置文件

<?xml version="1.0" encoding="UTF-8"?>


 

1.3.3、配置DBCP数据源

Spring 框架也提供了一个内置数据源,我们也可以使用 spring 的内置数据源,它就在spring-jdbc.jar中
 

        
        
        
        

以上这两种都可以使用,任意选一种即可。

1.4、增删改查
1.4.1、配置jdbcTemplate

<?xml version="1.0" encoding="UTF-8"?>

 

1.4.2、基本用法
public static void main(String[] args) {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(“com.mysql.jdbc.Driver”);
ds.setUrl(“jdbc:mysql://localhost:3306/ssm”);
ds.setUsername(“root”);
ds.setPassword(“root”);

//1.创建JdbcTemplate对象
JdbcTemplate jt = new JdbcTemplate();
//给jt设置数据源
jt.setDataSource(ds);
//2.执行操作
jt.execute("insert into t_user(username,password)values('ccc','aaa')");

}

1.4.2、Spring整合后的基本用法
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
JdbcTemplate jt = (JdbcTemplate) context.getBean(“jdbcTemplate”);
//jdbcTemplate.execute(“insert into t_user(username,password)values(‘张美玲’,‘888’)”);
// 查询所有
List accounts = jt.query(“select * from t_user”,new UserRowMapper());
for (User account : accounts) {
System.out.println(account);
}
System.out.println(“--------”);
User user = jt.queryForObject(“select * from t_user where id = ?”,new BeanPropertyRowMapper(User.class),1);
System.out.println(user);

System.out.println(“--------”);
//返id大于3的总条数
Integer count = jt.queryForObject(“select count(*) from t_user where id > ?”, Integer.class, 3);
System.out.println(count);
//多条件查询 、模糊查询
List ulist = jt.query(“select * from t_user where t_user.username like ? and nickname like ? “,new UserRowMapper(),new Object[]{”%a%”,“%a%”});
System.out.println(ulist.size());
for (User user1 : ulist) {
System.out.println(user1);
}
定义User的封装策略
public class UserRowMapper implements RowMapper {

@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
    User u = new User();
    u.setId(rs.getInt("id"));
    u.setUsername(rs.getString("username"));
    return u;
}

}

1.5、Dao中添加JdbcTemplate
1.5.1、实体类
public class User {
private Integer id;
private String username;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

@Override
public String toString() {
    return "User{" +
            "id=" + id +
            ", username='" + username + '\'' +
            '}';
}

}
1.5.2、定义IUserDao接口
public interface IUserDao {
//添加一条用户信息
void add(User user);
//根据id删除一条数据
void delete(Integer id);
//修改一条数据
void update(User user);
//根据条件查询用户信息列表
List getUserList(User user);
//根据id查询一条数据
User getUserById(Integer id);
//获取总条数
Integer getListCount();
}
1.5.3、在UserDaoImpl实现类中添加jdbcTemplate
public class UserDaoImpl implements IUserDao {

private JdbcTemplate jdbcTemplate;

@Override
public void add(User user) {
    String sql = " insert into t_user(username) values('"+user.getUsername()+"') ";
    jdbcTemplate.execute(sql);
}

@Override
public void delete(Integer id) {
    String sql = "delete from t_user where id = "+id+"";
    jdbcTemplate.execute(sql);
}

@Override
public void update(User user) {
    String sql = "update t_user set username = '"+user.getUsername()+"' where id = "+user.getId()+"";
    jdbcTemplate.execute(sql);
}

@Override
public List<User> getUserList(User user) {
    String sql = " select * from t_user where 1=1 ";
    if(user.getUsername()!=null){
        sql += "and username like '%"+user.getUsername()+"%'";
    }
    return jdbcTemplate.query(sql,new UserRowMapper());
}

@Override
public User getUserById(Integer id) {
    String sql = " select * from t_user where id = "+id+" ";
    return jdbcTemplate.queryForObject(sql,new UserRowMapper());
}

@Override
public Integer getListCount() {
    String sql = "select count(*) from t_user where username like '%美%'";
    return jdbcTemplate.queryForObject(sql,Integer.class);
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
}

}
1.5.4、在配置文件中给UserDaoImpl注入jdbcTemplate

<?xml version="1.0" encoding="UTF-8"?>

    1.5.5、测试 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); JdbcTemplate jt = (JdbcTemplate) context.getBean("jdbcTemplate"); //jdbcTemplate.execute("insert into t_user(username,password)values('张美玲','888')"); // 查询所有 List accounts = jt.query("select * from t_user",new UserRowMapper()); for (User account : accounts) { System.out.println(account); } System.out.println("--------"); //根据id查询一条数据 User user = jt.queryForObject("select * from t_user where id = ?",new BeanPropertyRowMapper(User.class),1); System.out.println(user);

System.out.println(“--------”);
//返id大于3的总条数
Integer count = jt.queryForObject(“select count(*) from t_user where id > ?”, Integer.class, 3);
System.out.println(count);
//多条件查询 、模糊查询
List ulist = jt.query(“select * from t_user where t_user.username like ? and nickname like ? “,new UserRowMapper(),new Object[]{”%a%”,“%a%”});
System.out.println(ulist.size());
for (User user1 : ulist) {
System.out.println(user1);
}
1.5.6、思考:
此种方式有什么问题吗?
答案:
有个小问题。就是我们的 dao 有很多时,每个 dao 都有一些重复性的代码。下面就是重复代码:
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
能不能把它抽取出来呢?请看下一小节。

1.5.7、继承JdbcDaoSupport
JdbcDaoSupport 是 spring 框架为我们提供的一个类,该类中定义了一个 JdbcTemplate 对象,我们可以直接获取使用,但是要想创建该对象,需要为其提供一个数据源:
具体源码如下:
 
public abstract class JdbcDaoSupport extends DaoSupport {
//定义对象
private JdbcTemplate jdbcTemplate;
//set 方法注入数据源,判断是否注入了,注入了就创建 JdbcTemplate
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
//如果提供了数据源就创建 JdbcTemplate
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}
//使用数据源创建 JdcbTemplate
protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
//当然,我们也可以通过注入 JdbcTemplate 对象
public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
initTemplateConfig();
}
//使用 getJdbcTmeplate 方法获取操作模板对象
public final JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}

1.5.8、UserDaoImpl实现类继承JdbcDaoSupport
public class UserDaoImpl2 extends JdbcDaoSupport implements IUserDao {

//private JdbcTemplate jdbcTemplate;

@Override
public void add(User user) {
    String sql = " insert into t_user(username) values('"+user.getUsername()+"') ";
    super.getJdbcTemplate().execute(sql);
}

@Override
public void delete(Integer id) {
    String sql = "delete from t_user where id = "+id+"";
    super.getJdbcTemplate().execute(sql);
}

1.5.9、在applicationContext.xml中给UserDaoImpl注入dataSource












1.5.10、测试
public class UserDaoImplTest2 {

private ApplicationContext context;

@Before
public void before(){
    context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void add(){
    IUserDao userDao = context.getBean(UserDaoImpl2.class);
    User user = new User();
    user.setUsername("乔森");
    userDao.add(user);
}
@Test
public void delete(){
    IUserDao userDao = context.getBean(UserDaoImpl2.class);
    userDao.delete(26);
}

1.5.11、测试
 
思考:
两版 Dao 有什么区别呢?
答案:
第一种在 Dao 类中定义 JdbcTemplate 的方式,适用于所有配置方式(xml 和注解都可以)。
第二种让 Dao 继承 JdbcDaoSupport 的方式,只能用于基于 XML 的方式,注解用不了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值