Spring框架详解介绍-基本使用方法

  • 1.Spring框架—控制反转(IOC)
  • 2.Spring框架—面向切面编程(AOP)
  • 3.Spring 内置的JdbcTemplate(Spring-JDBC)

Spring框架—控制反转(IOC)

1 Spring框架概述

1.1 什么是Spring

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

1.2 Spring的优点
  • 方便解耦,简化开发 (高内聚低耦合) 
    Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理 
    spring工厂是用于生成bean
  • AOP编程的支持 
    Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
  • 声明式事务的支持 
    只需要通过配置就可以完成对事务的管理,而无需手动编程
  • 方便程序的测试 
    Spring对Junit4支持,可以通过注解方便的测试Spring程序
  • 方便集成各种优秀框架 
    Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
  • 降低JavaEE API的使用难度 
    Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
1.3 Spring的体系结构

这里写图片描述

2 入门案例:(IoC)

2.1导入jar包
  • 4 + 1 : 4个核心(beans、core、context、expression) + 1个依赖(commons-loggins…jar) 
    这里写图片描述 
    这里写图片描述
2.2目标类
  • 提供UserService接口和实现类
  • 获得UserService实现类的实例 
    之前开发中,直接new一个对象即可。学习spring之后,将由Spring创建对象实例–> IoC 控制反转(Inverse of Control) 
    之后需要实例对象时,从spring工厂(容器)中获得,需要将实现类的全限定名称配置到xml文件中
public interface UserService {
    public void addUser();
}
public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("a_ico add user");
    }
}
2.3 配置文件
  • 位置:任意,开发中一般在classpath下(src)
  • 名称:任意,开发中常用applicationContext.xml
  • 内容:添加schema约束 
    约束文件位置:spring-framework-3.2.0.RELEASE\docs\spring-framework-reference\html\ xsd-config.html
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 配置service 
        <bean> 配置需要创建的对象
            id :用于之后从spring容器获得实例时使用的
            class :需要创建实例的全限定类名
    -->
    <bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl"></bean>
</beans>

2.4测试
   @Test
    public void demo02(){
        //从spring容器获得
        //1 获得容器
        String xmlPath = "com/itheima/a_ioc/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        //2获得内容 --不需要自己new,都是从spring容器获得
        UserService userService = (UserService) applicationContext.getBean("userServiceId");
        userService.addUser();  

3 入门案例:DI

  • 例如:

    class BookServiceImpl{
        //之前开发:接口 = 实现类  (service和dao耦合)
        //private BookDao bookDao = new BookDaoImpl();
        //spring之后 (解耦:service实现类使用dao接口,不知道具体的实现类)
        private BookDao bookDao;
        setter方法
    }
    模拟spring执行过程
    创建service实例:BookService bookService = new BookServiceImpl()     -->IoC  <bean>
    创建dao实例:BookDao bookDao = new BookDaoImple()                -->IoC
    将dao设置给service:bookService.setBookDao(bookDao);             -->DI   <property>
3.1 目标类
  • 创建BookService接口和实现类
  • 创建BookDao接口和实现类
  • 将dao和service配置 xml文件
  • 使用api测试
3.2 dao
public interface BookDao {
    public void save();
}
public class BookDaoImpl implements BookDao {

    @Override
    public void save() {
        System.out.println("di  add book");
    }
}
3.3 service
public interface BookService {

    public abstract void addBook();

}
public class BookServiceImpl implements BookService {

    // 方式1:之前,接口=实现类
//  private BookDao bookDao = new BookDaoImpl();
    // 方式2:接口 + setter
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void addBook(){
        this.bookDao.save();
    }

}
3.4 配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 
    模拟spring执行过程
        创建service实例:BookService bookService = new BookServiceImpl() IoC  <bean>
        创建dao实例:BookDao bookDao = new BookDaoImpl()         IoC
        将dao设置给service:bookService.setBookDao(bookDao);     DI   <property>

        <property> 用于进行属性注入
            name: bean的属性名,通过setter方法获得
                setBookDao ##> BookDao  ##> bookDao
            ref :另一个bean的id值的引用
     -->

    <!-- 创建service -->
    <bean id="bookServiceId" class="com.itheima.b_di.BookServiceImpl">
        <property name="bookDao" ref="bookDaoId"></property>
    </bean>

    <!-- 创建dao实例 -->
    <bean id="bookDaoId" class="com.itheima.b_di.BookDaoImpl"></bean>


</beans>
3.5 测试
    @Test
    public void demo01(){
        //从spring容器获得
        String xmlPath = "com/itheima/b_di/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        BookService bookService = (BookService) applicationContext.getBean("bookServiceId");    
        bookService.addBook();
    }

4 依赖注入装配Bean 基于xml

4.1属性依赖注入
  • 依赖注入方式:手动装配 和 自动装配 
    • 手动装配:一般进行配置信息都采用手动 
      基于xml装配:构造方法、setter方法
    • 基于注解装配:
4.1.1 构造方法

目标类

public class User {

    private Integer uid;
    private String username;
    private Integer age;

    public User(Integer uid, String username) {
        super();
        this.uid = uid;
        this.username = username;
    }

    public User(String username, Integer age) {
        super();
        this.username = username;
        this.age = age;
    }

spring配置

    <!-- 构造方法注入 
        * <constructor-arg> 用于配置构造方法一个参数argument
            name :参数的名称
            value:设置普通数据
            ref:引用数据,一般是另一个bean id值

            index :参数的索引号,从0开始 。如果只有索引,匹配到了多个构造方法时,默认使用第一个。
            type :确定参数类型
        例如:使用名称name
            <constructor-arg name="username" value="jack"></constructor-arg>
            <constructor-arg name="age" value="18"></constructor-arg>
        例如2:【类型type 和  索引 index】
            <constructor-arg index="0" type="java.lang.String" value="1"></constructor-arg>
            <constructor-arg index="1" type="java.lang.Integer" value="2"></constructor-arg>
    -->
    <bean id="userId" class="com.itheima.f_xml.a_constructor.User" >
        <constructor-arg index="0" type="java.lang.String" value="1"></constructor-arg>
        <constructor-arg index="1" type="java.lang.Integer" value="2"></constructor-arg>
    </bean>
4.1.2 setter方法
<!-- setter方法注入 
        * 普通数据 
            <property name="" value="值">
            等效
            <property name="">
                <value>值
        * 引用数据
            <property name="" ref="另一个bean">
            等效
            <property name="">
                <ref bean="另一个bean"/>

    -->
    <bean id="personId" class="com.itheima.f_xml.b_setter.Person">
        <property name="pname" value="阳志"></property>
        <property name="age">
            <value>1234</value>
        </property>

        <property name="homeAddr" ref="homeAddrId"></property>
        <property name="companyAddr">
            <ref bean="companyAddrId"/>
        </property>
    </bean>

    <bean id="homeAddrId" class="com.itheima.f_xml.b_setter.Address">
        <property name="addr" value="阜南"></property>
        <property name="tel" value="911"></property>
    </bean>
    <bean id="companyAddrId" class="com.itheima.f_xml.b_setter.Address">
        <property name="addr" value="北京八宝山"></property>
        <property name="tel" value="120"></property>
    </bean>
4.2 集合依赖注入
<!-- 
        集合的注入都是给<property>添加子标签
            数组:<array>
            List:<list>
            Set:<set>
            Map:<map> ,map存放k/v 键值对,使用<entry>描述
            Properties:<props>  <prop key=""></prop>  【】

        普通数据:<value>
        引用数据:<ref>
    -->
    <bean id="collDataId" class="com.itheima.f_xml.e_coll.CollData" >
        <property name="arrayData">
            <array>
                <value>DS</value>
                <value>DZD</value>
                <value>屌丝</value>
                <value>屌中屌</value>
            </array>
        </property>

        <property name="listData">
            <list>
                <value>于嵩楠</value>
                <value>曾卫</value>
                <value>杨煜</value>
                <value>曾小贤</value>
            </list>
        </property>

        <property name="setData">
            <set>
                <value>停封</value>
                <value>薄纸</value>
                <value>关系</value>
            </set>
        </property>

        <property name="mapData">
            <map>
                <entry key="jack" value="杰克"></entry>
                <entry>
                    <key><value>rose</value></key>
                    <value>肉丝</value>
                </entry>
            </map>
        </property>

        <property name="propsData">
            <props>
                <prop key="高富帅"></prop>
                <prop key="白富美"></prop>
                <prop key="男屌丝"></prop>
            </props>
        </property>
    </bean>

5 依赖注入装配Bean 基于注解

  • 注解:就是一个类,使用@注解名称
  • 开发中:使用注解 取代 xml配置文件。 
    1.@Component取代<bean class=""> 
    @Component("id") 取代 <bean id="" class=""> 
    2.web开发,提供3个@Component注解衍生注解(功能一样)取代 
    @Repository :dao层 
    @Service:service层 
    @Controller:web层 
    3.依赖注入,给私有字段设值,也可以给setter方法设值

    • 普通值:@Value(" ")
    • 引用值: 
      方式1:按照【类型】注入 
      @Autowired 
      方式2:按照【名称】注入1 
      @Autowired 
      @Qualifier("名称") 
      方式3:按照【名称】注入2 
      @Resource("名称")
       
      4.生命周期 
      初始化:@PostConstruct 
      销毁:@PreDestroy
       
      5.作用域 
      @Scope("prototype") 多例 
      注解使用前提,添加命名空间,让spring扫描含有注解类 
      
      <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 
                             http://www.springframework.org/schema/context/spring-context.xsd">
      <!-- 组件扫描,扫描含有注解的类 -->
      <context:component-scan base-package="com.itheima.g_annotation.a_ioc"></context:component-scan>
      </beans>

Spring框架—面向切面编程(AOP)

1 什么是AOP

  • 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  • AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
  • 经典应用:事务管理、性能监视、安全检查、缓存 、日志等
  • Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
  • AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

2 AOP实现原理

  • aop底层将采用代理机制进行实现。
  • 接口 + 实现类 :spring采用 jdk 的动态代理Proxy。
  • 实现类:spring 采用 cglib字节码增强。

3 AOP术语【掌握】

1.target:目标类,需要被代理的类。例如:UserService 
2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法 
3.PointCut 切入点:已经被增强的连接点。例如:addUser() 
4.advice 通知/增强,增强代码。例如:after、before 
5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程. 
6.proxy 代理类 
7. Aspect(切面): 是切入点pointcut和通知advice的结合 
一个线是一个特殊的面。 
一个切入点和一个通知,组成成一个特殊的面。 
这里写图片描述

4 AOP实现方式

4.1手动方式

4.1.1JDK动态代理
  • JDK动态代理 对“装饰者”设计模式 简化。使用前提:必须有接口

1.目标类:接口 + 实现类

public interface UserService {
    public void addUser();
    public void updateUser();
    public void deleteUser();
}

2.切面类:用于存通知 MyAspect

public class MyAspect { 
    public void before(){
        System.out.println("鸡首");
    }   
    public void after(){
        System.out.println("牛后");
    }
}

3.工厂类:编写工厂生成代理

public class MyBeanFactory {

    public static UserService createService(){
        //1 目标类
        final UserService userService = new UserServiceImpl();
        //2切面类
        final MyAspect myAspect = new MyAspect();
        /* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
         *  Proxy.newProxyInstance
         *      参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
         *          一般情况:当前类.class.getClassLoader();
         *                  目标类实例.getClass().get...
         *      参数2:Class[] interfaces 代理类需要实现的所有接口
         *          方式1:目标类实例.getClass().getInterfaces()  ;注意:只能获得自己接口,不能获得父元素接口
         *          方式2:new Class[]{UserService.class}   
         *          例如:jdbc 驱动  --> DriverManager  获得接口 Connection
         *      参数3:InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部
         *          提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
         *              参数31:Object proxy :代理对象
         *              参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
         *                  执行方法名:method.getName()
         *                  执行方法:method.invoke(对象,实际参数)
         *              参数33:Object[] args :方法实际参数
         * 
         */
        UserService proxService = (UserService)Proxy.newProxyInstance(
                                MyBeanFactory.class.getClassLoader(), 
                                userService.getClass().getInterfaces(), 
                                new InvocationHandler() {

                                    @Override
                                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                                        //前执行
                                        myAspect.before();

                                        //执行目标类的方法
                                        Object obj = method.invoke(userService, args);

                                        //后执行
                                        myAspect.after();

                                        return obj;
                                    }
                                });

        return proxService;
    }

}

4.测试

@Test
    public void demo01(){
        UserService userService = MyBeanFactory.createService();
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }
4.1.2 CGLIB字节码增强
  • 没有接口,只有实现类。
  • 采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。

工厂类

public class MyBeanFactory {

    public static UserServiceImpl createService(){
        //1 目标类
        final UserServiceImpl userService = new UserServiceImpl();
        //2切面类
        final MyAspect myAspect = new MyAspect();
        // 3.代理类 ,采用cglib,底层创建目标类的子类
        //3.1 核心类
        Enhancer enhancer = new Enhancer();
        //3.2 确定父类
        enhancer.setSuperclass(userService.getClass());
        /* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
         *  intercept() 等效 jdk  invoke()
         *      参数1、参数2、参数3:以invoke一样
         *      参数4:methodProxy 方法的代理
         *      
         * 
         */
        enhancer.setCallback(new MethodInterceptor(){

            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

                //前
                myAspect.before();

                //执行目标类的方法
                Object obj = method.invoke(userService, args);
                // * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
                methodProxy.invokeSuper(proxy, args);

                //后
                myAspect.after();

                return obj;
            }
        });
        //3.4 创建代理
        UserServiceImpl proxService = (UserServiceImpl) enhancer.create();

        return proxService;
    }

}

4.2半自动

  • 让spring 创建代理对象,从spring容器中手动的获取代理对象
4.2.1目标类
public interface UserService {
    public void addUser();
    public void updateUser();
    public void deleteUser();
}
4.2.2切面类
/**
 * 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
 * * 采用“环绕通知” MethodInterceptor
 *
 */
public class MyAspect implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {

        System.out.println("前3");

        //手动执行目标方法
        Object obj = mi.proceed();

        System.out.println("后3");
        return obj;
    }
}
4.2.3Spring 配置
<!-- 1 创建目标类 -->
    <bean id="userServiceId" class="com.itheima.b_factory_bean.UserServiceImpl"></bean>
    <!-- 2 创建切面类 -->
    <bean id="myAspectId" class="com.itheima.b_factory_bean.MyAspect"></bean>

    <!-- 3 创建代理类 
        * 使用工厂bean FactoryBean ,底层调用 getObject() 返回特殊bean
        * ProxyFactoryBean 用于创建代理工厂bean,生成特殊代理对象
            interfaces : 确定接口们
                通过<array>可以设置多个值
                只有一个值时,value=""
            target : 确定目标类
            interceptorNames : 通知 切面类的名称,类型String[],如果设置一个值 value=""
            optimize :强制使用cglib
                <property name="optimize" value="true"></property>
        底层机制
            如果目标类有接口,采用jdk动态代理
            如果没有接口,采用cglib 字节码增强
            如果声明 optimize = true ,无论是否有接口,都采用cglib

    -->
    <bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="com.itheima.b_factory_bean.UserService"></property>
        <property name="target" ref="userServiceId"></property>
        <property name="interceptorNames" value="myAspectId"></property>
    </bean>
4.2.4 测试
    @Test
    public void demo01(){
        String xmlPath = "com/itheima/b_factory_bean/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        //获得代理类
        UserService userService = (UserService) applicationContext.getBean("proxyServiceId");
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

4.3全自动

  • 从spring容器获得目标类,如果配置aop,spring将自动生成代理。
4.3.1 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 1 创建目标类 -->
    <bean id="userServiceId" class="com.itheima.c_spring_aop.UserServiceImpl"></bean>
    <!-- 2 创建切面类(通知) -->
    <bean id="myAspectId" class="com.itheima.c_spring_aop.MyAspect"></bean>
    <!-- 3 aop编程 
        3.1 导入命名空间
        3.2 使用 <aop:config>进行配置
                proxy-target-class="true" 声明时使用cglib代理
            <aop:pointcut> 切入点 ,从目标对象获得具体方法
            <aop:advisor> 特殊的切面,只有一个通知 和 一个切入点
                advice-ref 通知引用
                pointcut-ref 切入点引用
        3.3 切入点表达式
            execution(* com.itheima.c_spring_aop.*.*(..))
            选择方法         返回值任意   包             类名任意   方法名任意   参数任意

    -->
    <aop:config proxy-target-class="true">
        <aop:pointcut expression="execution(* com.itheima.c_spring_aop.*.*(..))" id="myPointCut"/>
        <aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/>
    </aop:config>
</beans>
4.3.2 测试

    @Test
    public void demo01(){
        String xmlPath = "com/itheima/c_spring_aop/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        //获得目标类
        UserService userService = (UserService) applicationContext.getBean("userServiceId");
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

使用Spring 内置的JdbcTemplate操作数据库

       hibernate是一个很好的ORM框架,使用Hibernate可以很好的提高开发效率,而且操作起来也是非常简单,但是Hibernate也有一定的灵活性限制,此时就可以使用spring内置的JDBC框架;JDBC框架是对纯JDBC的一个封装,简化了一些繁琐的操作,而且可以自己编写sql语句,灵活的处理业务。
        Spring JDBC框架(spring-jdbc-x.x.x.RELEASE.jar)由4个部分组成:
——core包:提供了JDBC模板类,JdbcTemplate是core包的核心类
——datasource包:提供简化访问JDBC数据源工具类,并提供一些DataSource简单实现类,从而使这些DataSource                                     获取的连接能自动得到Spring事务管理的支持
——object包:提供关系数据的对象表现形式,如MappingSqlQuery、SqlUpdate、SqlCall、SqlFunction等。
——support包:提供将JDBC异常转换为Dao非检查异常的转换类和一些工具类

一、基本操作

1.主要的实现步骤

(1)编写spring配置文件applicationContext.xml:

[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans  
  3.     xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xmlns:p="http://www.springframework.org/schema/p"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">  
  7.       
  8.     <!-- 1.配置数据源:DriverManagerDataSource -->  
  9.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  10.         <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>  
  11.         <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>  
  12.         <property name="username" value="scott"/>  
  13.         <property name="password" value="tiger"/>  
  14.     </bean>  
  15.     <!--2.配置JdbcTemplate -->  
  16.     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
  17.         <property name="dataSource" ref="dataSource"/>  
  18.     </bean>  
  19.     <!-- 3.为dao接口注入jdbcTemplate属性 -->  
  20.     <bean id="userDao" class="com.wzj.dao.impl.UserDaoImpl">  
  21.         <property name="jdbcTemplate" ref="jdbcTemplate"/>  
  22.     </bean>  
  23.       
  24.     <!-- 业务层 、Struts2、事务等同往常一样配置-->  
  25.   
  26.   
  27. </beans>  

(2)在dao接口中使用JdbcTemplate实现方法的实现:

[java] view plain copy
  1. package com.wzj.dao.impl;  
  2.   
  3. import java.sql.ResultSet;  
  4. import java.sql.SQLException;  
  5.   
  6. import org.springframework.jdbc.core.JdbcTemplate;  
  7. import org.springframework.jdbc.core.RowMapper;  
  8.   
  9. import com.wzj.dao.UserDao;  
  10. import com.wzj.entity.User;  
  11.   
  12. public class UserDaoImpl implements UserDao{  
  13.     //定义JdbcTemplate属性  
  14.     private JdbcTemplate jdbcTemplate;  
  15.     //省略get、set方法  
  16.     @Override  
  17.     public User selectUserByName(String name) {  
  18.         //定义RowMapper的对象,可以将数据中的每一行数据封装成用户定义的类.  
  19.         //RowMapper是接口,这里创建了一个匿名类并实现了其中的方法  
  20.         RowMapper<User> row=new RowMapper<User>() {  
  21.             @Override  
  22.             public User mapRow(ResultSet rs, int arg1) throws SQLException {  
  23.                 User user=new User();  
  24.                 user.setUserId(Integer.parseInt(rs.getString("USERID")));  
  25.                 user.setName(rs.getString("USERNAME"));  
  26.                 user.setPassword(rs.getString("USERPWD"));  
  27.                 return user;  
  28.             }  
  29.         };   
  30.         String sql="select * from myuser1 where username=?";  
  31.         //执行查询  
  32.         User user=jdbcTemplate.queryForObject(sql, new Object[]{name}, row);  
  33.         return user;  
  34.     }  
  35.   
  36.   
  37.     @Override  
  38.     public int insert(User user) {  
  39.         String sql="insert into myuser1 values(user_sequence.nextVal,?,?)";  
  40.         //执行插入  
  41.         int result=jdbcTemplate.update(sql, new Object[]{user.getName(),user.getPassword()});  
  42.         return result;  
  43.     }  
  44.   
  45.   
  46.     @Override  
  47.     public int delete(int userId) {  
  48.         String sql="delete from myuser1 where userid=?";  
  49.         //执行修改  
  50.         int result=jdbcTemplate.update(sql, new Object[]{userId});  
  51.         return result;  
  52.     }  
  53.   
  54.   
  55.     @Override  
  56.     public int update(User user) {  
  57.         String sql="update myuser1 set username=?,userpwd=? where userid=?";  
  58.         //执行删除  
  59.         int result=jdbcTemplate.update(sql, new Object[]{user.getName(),user.getPassword(),user.getUserId()});  
  60.         return result;  
  61.     }  
  62.       
  63. }  

2.JdbcTemplate类的常用方法

方法名称说明
void execute(String sql)可以用于任何sql语句
int update(String sql,Object..args)执行DML语句,如UPDATE、INSERT、DELETE,args是其对应的参数
List<T> query(String sql,RowMapper<T> rowMapper)执行sql查询语句,并根据RowMapper具体的实现类返回结果类型
int queryForInt(String sql)queryForXXX(),XXX代表结果类型,执行sql查询语句,返回结果是整数
T queryForObject(String sql,Object[] args,RowMapper<T> rowMapper)根据sql语句和参数返回结果对象
List<Map<String,Object>> queryForList(String sql,Object..args)根据sql语句和参数返回结果列表,每个Map的key是列名,value是该列对应的数据

二、调用存储过程

Spring JdbcTemplate支持对存储过程的调用(JDK最低1.5版本),JdbcTemplate支持的存储过程回调类如下:

——CallableStatementCreator:

通过回调获取JdbcTemplate提供的Connection,由用户使用该Connection创建相关的CallableStatement

——CallableStatementCallback:

通过回调获取JdbcTemplate提供的CallableStatement,用户可以再CallableStatement执行任何操作

(1)执行无返回值的存储过程:

[java] view plain copy
  1. package com.wzj.test;  
  2.   
  3.   
  4. import org.springframework.jdbc.core.JdbcTemplate;  
  5.   
  6.   
  7. public class Demo{  
  8.     private JdbcTemplate jdbcTemplate;  
  9.     //省略get、set  
  10.       
  11.     public void test(){  
  12.         jdbcTemplate.execute("{call procedureName(param,param...)}");  
  13.     }  
  14. }  

(2)执行返回非结果集的存储过程:

创建存储过程:
  1. create or replace procedure get_user_name(id in varchar2,username out varchar2) is  
  2. begin  
  3.     select username from User where userid=id;  
  4. end  
调用:
[java] view plain copy
  1. public void test(){  
  2.     jdbcTemplate.execute(new CallableStatementCreator() {  
  3.         @Override  
  4.         public CallableStatement createCallableStatement(Connection con)  
  5.                 throws SQLException {  
  6.             String userid="22";  
  7.             //创建对象  
  8.             CallableStatement cs=con.prepareCall("call get_user_name(?,?)");  
  9.             //设置参数  
  10.             cs.setString(1, userid);  
  11.             //设置输出参数  
  12.             cs.registerOutParameter(2, OracleTypes.VARCHAR);  
  13.             return cs;  
  14.         }  
  15.     }, new CallableStatementCallback() {  
  16.         @Override  
  17.         public Object doInCallableStatement(CallableStatement cs)  
  18.                 throws SQLException, DataAccessException {  
  19.             //执行存储过程  
  20.             cs.execute();  
  21.             //获取输出参数  
  22.             return cs.getString(2);  
  23.         }  
  24.     });  
  25. }  

(3)执行返回结果集的存储过程:

①建立程序包:
  1. create or replace package userpackage as   
  2.   type user_cursor is ref cursor;   
  3. end userpackage;   
②创建存储过程:
  1. create or replace procedure get_user(user_cursor out userpackage.user_cursor) is   
  2. begin   
  3.      open user_cursor for select * from User;   
  4. end;   
③调用:
[java] view plain copy
  1. public void test() {   
  2.     List userList = (List) jdbcTemplate.execute(   
  3.             new CallableStatementCreator() {   
  4.                 public CallableStatement createCallableStatement(Connection con) throws SQLException {   
  5.                     CallableStatement cs = con.prepareCall("{call get_user(?)}");   
  6.                     cs.registerOutParameter(1, OracleTypes.CURSOR);// 注册输出参数的类型   
  7.                     return cs;   
  8.                 }   
  9.             }, new CallableStatementCallback() {   
  10.                 public Object doInCallableStatement(CallableStatement cs) throws SQLException,DataAccessException {   
  11.                     List userMap = new ArrayList();   
  12.                     cs.execute();   
  13.                     ResultSet rs = (ResultSet) cs.getObject(1);// 获取游标一行的值   
  14.                     while (rs.next()) {// 转换每行的返回值到Map中   
  15.                         Map rowMap = new HashMap();   
  16.                         rowMap.put("userid", rs.getString("userid"));   
  17.                         rowMap.put("username", rs.getString("username"));   
  18.                         userMap.add(rowMap);   
  19.                     }   
  20.                     rs.close();   
  21.                     return userMap;   
  22.                 }   
  23.             });   
  24.     for (int i = 0; i < userList.size(); i++) {   
  25.         Map rowMap = (Map) userList.get(i);   
  26.         String id = rowMap.get("userid").toString();   
  27.         String name = rowMap.get("username").toString();   
  28.         System.out.println("usreid=" + id + ";username=" + name);   
  29.     }   
  30. }   
Spring详解-Mike zhong
posted @ 2018-04-28 12:29  gqzdev  阅读(768)  评论(0编辑  收藏  举报