Spring框架-ioc和JdbcTemplate

前提

​ 我们用了Mybatis时,已经不需要再使用其他的持久层框架了。用了mybatis之后,我们只需要写持久层接口以及sql语句即可。

但是为了讲解spring中的事务,我们把JdbcTemplate拿出来讲,使用JdbcTemplate需要编写持久层实现类。

​ 此时有两个目的:

​ 第一个:通过JdbcTemplate去铺垫Spring第三天课程的事务控制。(配置的方式实现)

​ 第二个:通过JdbcTemplate去更加深入掌握依赖注入思想(今天就说明明白)

spring的课程安排

  1. 课程时长: 共5天。其中spring框架3天,springmvc框架2天

  2. Spring3天:

    ​ Spring基于XML的IOC 第一天

    ​ Spring基于注解的IOC 第二天

         Spring的AOP(xml和注解)以及Spring的事务控制(XML和注解) 第三天
    
    3. SpringMVC 2天:
    

    ​ SpringMVC的请求部分

    ​ SpringMVC的响应部分和SSM整合(Spring+SpringMVC+Mybatis)

第一章 Spring介绍(了解)

1.1 概述

Spring是分层的Java SE/EE应用 full-stack(全栈式)轻量级开源框架,以IoCInverse Of Control:反转控制)和AOPAspect Oriented Programming:面向切面编程)为内核,提供了展现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。

其中full stack意为全栈式,在基于Java SE/EE的开发中,Spring框架各个部分的解决方案,例如持久层操作有Spring Jdbc/Spring Data,表现层操作有Spring MVC,Spring WebFlow等等,当然它还有很多针对项目特定需求的技术框架,在随着我们课程的深入,会逐步给同学们展现和讲解。

在我们今天讲解的Spring课程指的是Spring Framework,我们可以通过官网查看,Spring的官方网址为:

https://spring.io,浏览器输入网址可以看到如下界面:

在这里插入图片描述

Spring是分层的Java应用轻量级开源框架,核心是IOC和AOP

* 分层:Spring在三层上都有自己的解决方案

* 轻量级:只启动Spring核心容器的时候,占用的内存少,耗费的资源少

* 开源:源代码开发

* 核心:IOC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)
       DI  Dependency Injection 依赖注入(如果被问到spring的3大核心,这个就是第三个)
	

1.2 体系架构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MvGoCmoc-1653818390668)(assets/image-20211205173342336.png)]

1.3 官方文档

在这里插入图片描述

第二章 SpringIOC入门(重点)

2.1 IOC介绍

对象的创建由原来的使用new关键字在类中主动创建变成了从工厂中获取,而对象的创建过程由工厂内部来实现,

而这个工厂就是Spring的IOC容器,也就是以后我们的对象不再自己创建,而是直接向Spring要,这种思想就是IOC

IOC(控制反转)是一种设计思想,它的目的是指导我们设计出更加松耦合的程序。

控制:指的是控制权,现在可以简单理解为对象的创建权限

反转:指的对象的控制权由程序员在类中主动控制(new)反转到由Spring容器来控制。

2.2 案例实现

使用Spring的IOC来实现service和dao代码的解耦

2.2.1 环境搭建

在这里插入图片描述

2.2.2基础代码编写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zDTEOGSs-1653818390672)(assets/image-20220525150939212.png)]

2.2.3配置文件

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

    <!--把service和dao的对象创建,都交给spring管理。
        也就是,在配置文件中配置service和dao

        使用的标签:
            bean标签
            标签的属性:
                id属性:用于指定存入map时的key,
                class属性:用于指定创建对象的全限定类名

            使用细节:
                id属性的取值,一般就是类名,把首字母改成小写。
    -->

    <!--配置service-->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>

    <!--配置dao-->
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
</beans>

2.2.4测试代码

package com.itheima.test;

import com.itheima.dao.UserDao;
import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Spring基于XML的ioc入门案例
 */
public class SpringIoCTest {

    public static void main(String[] args) {
        //1.读取spring的配置文件,创建ioc容器(我们就可以把他想成是一个map)
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        //2.根据存入时的id获取对象
        UserDao userDao = (UserDao)ac.getBean("userDao");
        UserService userService = ac.getBean("userService", UserService.class);

        //取到的对象,他是spring帮我们创建并且存入ioc容器的
        System.out.println(userDao);
        System.out.println(userService);

        userService.saveUser();
    }
}

2.3要点分析

  1. SpringIOC容器启动过程中要做哪些操作

    ![[]](https://img-blog.csdnimg.cn/8a3f7b3154cc4f1ab225b584f0f76db4.png)

  2. SpringIOC存储对象的Map到底在哪里
    在这里插入图片描述

2.4API(了解)

2.4.1两个接口

* BeanFactory
	这是SpringIOC容器的顶级接口,它定义了SpringIOC的最基础的功能,但是其功能比较简单,一般面向Spring自身使用
	BeanFactroy在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化

* ApplicationContext
	这是在BeanFactory基础上衍生出的接口,它扩展了BeanFactory的功能,一般面向程序员使用 
	ApplicationContext是在容器启动时,根据用户的配置选择一次性创建并加载了所有的Bean,或者在使用时才创建Bean

* 注意: 上面两种方式创建的对象都是单例,只是创建对象的时机不同


bean 指的就是我们写在spring配置文件中的对象

2.4.2三个实现类

* 这三个类的作用都是:读取配置文件, 初始化Spring的IOC容器,  不一样的是加载配置文件的位置
	- ClassPathXmlApplicationContext         读取类路径下的xml作为配置文件
	- FileSystemXmlApplicationContext        读取本地目录下的xml作为配置文件	
	- AnnotationConfigApplicationContext     读取一个Java类作为配置文件

在这里插入图片描述

2.4.3一个方法

* getBean() 用于从Spring容器中获取Bean对象,参数可以使用三种情况:
	getBean("id")                     使用bean的id从容器中查找对象
	getBean(Bean.class)               使用bean的class类型从容器中查找对象
	getBean("id", Bean.class)         使用bean的id 和 class类型从容器中查找对象

第三章Bean的配置(重点)

3.1bean的创建方式

3.1.1环境准备

package com.itheima.service;

/**
 * 用户的业务层接口
 */
public interface UserService {

    /**
     * 模拟一个业务层方法
     */
    void saveUser();
}

package com.itheima.service.impl;

import com.itheima.service.UserService;

/**
 * 用户的业务层实现类
 *
 * 此处我们用此类和类中的方法演示bean定义的细节
 */
public class UserServiceImpl implements UserService {

    /**
     * 构造方法
     */
    public UserServiceImpl(){
        System.out.println("对象创建了");
    }

    /**
     * 初始化方法
     */
    public void init(){
        System.out.println("对象初始化好了");
    }

    /**
     * 销毁方法
     */
    public void destroy(){
        System.out.println("对象销毁了");
    }

    @Override
    public void saveUser() {
        System.out.println("此处就是业务层调用持久层实现功能");
    }
}

3.1.2创建对象的三种方式(了解)

我们常用的创建对象的方式有三种:

  1. 直接使用new关键字创建
  2. 使用静态工厂创建
  3. 使用实例化工厂创建

3.1.3直接调用构造函数创建

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
		
		
		<!--bean的定义细节:
		       第一个细节:Bean的三种创建方式
		            使用默认构造函数创建:用的最多的
		            使用静态工厂创建:一般用在引入的第三方工具包中
		            使用普通工厂创建:一般用在引入的第三方工具包中
		       第二个细节:Bean的作用范围(单例bean和多例bean)
		       第三个细节:Bean的生命周(由作用范围引出的)
		-->

    <!--把service交给spring来管理-->
    <!--第一种创建方式:通过类中的默认构造函数创建。
    此时他是反射调用默认无参构造创建的对象,并存入了ioc容器。
    因此,如果没有默认构造函数的话,这么写会报错。-->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
</beans>

3.1.4使用静态工厂创建

package com.itheima.factory;

import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;

/**
 * 静态工厂
 *
 */
public class StaticFactory {

    /**
     * 模拟使用第三方工具包来创建对象
     * 第三方工具包中的对象没法使用默认构造函数创建
     * 而是提供了一个工厂,在工厂中有一个静态方法,这个方法可以获取到我们想要的对象
     * 那么spring是支持把他配置到ioc容器的
     * @return
     */
    public static UserService createUserService(){
        return  new UserServiceImpl();
    }
}

    <!--第二种创建方式:通过静态工厂的方式来创建bean对象的配置-->
    <bean id="userService2" class="com.itheima.factory.StaticFactory" factory-method="createUserService"></bean>

3.1.5使用实例化工厂创建

package com.itheima.factory;

import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;

/**
 * 实例工厂
 *
 */
public class InstanceFactory {

    /**
     * 模拟使用第三方工具包来创建对象
     * 第三方工具包中的对象没法使用默认构造函数创建
     * 而是提供了一个工厂,在工厂中有一个普通方法,这个方法可以获取到我们想要的对象
     * 那么spring是支持把他配置到ioc容器的
     * @return
     */
    public UserService createUserService(){
        return  new UserServiceImpl();
    }
}

    <!--第三种创建方式:通过普通工厂的方法来创建bean对象的配置-->
    <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="userService3" factory-bean="instanceFactory" factory-method="createUserService"></bean>

3.2bean的作用域

* 在Spring中,对于bean支持多种作用域,常见的有下面几个:
- singleton(默认)    单例模式,即对象只创建一次, 然后一直存在
- prototype          多例模式,即每次获取bean的时候,IOC 都给我们创建一个新对象
- request            web项目中,Spring创建一个Bean的对象,将对象存入到request域中
- session            web 项目中,Spring 创建一个Bean 的对象,将对象存入到session域中
 <!--bean的作用范围:  
          默认情况下bean的作用范围都是,只要ioc容器一创建完成,就会把bean对象创建好,并存入ioc容器。在整个应用中,只有一个容器和每个bean对象只有一个。
          但是spring支持配置的方式来指定不同的作用范围,配置的方式是:bean标签的scope属性。
                singleton  : 单例bean,一个用只有一个bean对象           一般的选择都是他
                prototype : 多例bean,每次使用时,都会创建新的对象
                request  :  请求范围,每次请求域发生变化时都会创建新的     基本很少用到
                session :  会话范围, 每次会话域发生变化时都会创建新的     基本很少用到
                global-session: 全局会话范围。他只有在集群环境下才能使用
  -->

    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl" scope="singleton"></bean>


3.3bean的生命周期

研究bean的生命周期,无非就是弄明白bean是什么时候创建的,什么时候销毁的

在Spring中,bean的作用范围会影响到其生命周期,所以我们要分单例和多例对象来研究bean的生命周期

    <!--
        bean的生命周期:
            单例bean(singleton)
                出生: 容器创建,bean对象出生
                活着: 只要容器在,bean对象一直可用
                死亡: 容器销毁,对象消亡
                一句话总结:单例bean的生命周期与容器相同。
            多例bean(prototype)
                出生:每次调用getBean方法时,创建对象
                活着:在bean对象的使用过程中,一直活着
                死亡:在对象长时间不用时,也没有别的对象引用时,有java的垃圾回收期回收。

    配置指定初始化和销毁方法
        init-method
        destroy-method
    -->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"
          scope="prototype" init-method="init" destroy-method="destroy"></bean>

3.4依赖注入(重点)

依赖注入(Dependency Injection,DI) 其实就是给对象中的属性赋值的过程

依赖注入有两种方式,分别是使用构造函数和set方法

3.4.1环境准备

package com.itheima.service;

/**
 * 用户的业务层接口
 */
public interface UserService {

    /**
     * 模拟一个业务层方法
     */
    void saveUser();
}

3.4.2构造函数注入

package com.itheima.service.impl;

import com.itheima.service.UserService;

import java.util.*;

/**
 * 用户的业务层实现类
 */
public class UserServiceImpl implements UserService {

    private String driver;//基本类型和String的演示
    private int port;//基本类型和String的演示

    private Date date;//其他bean类型的演示

    private String[] myStrs;//数组类型的演示
    private List<String> myList;//list集合类型的演示
    private Set<String> mySet;//set集合类型的演示
    private Map<String,String> myMap;//map集合的类型的演示
    private Properties myProps;//properties类型的演示

    public UserServiceImpl(String driver, int port, Date date) {
        this.driver = driver;
        this.port = port;
        this.date = date;
    }

    @Override
    public void saveUser() {
        System.out.println(driver);
        System.out.println(port);
        System.out.println(date);
    }
}
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        spring的依赖注入:
            Dependency Injection
            含义就是:
                把当前bean中依赖的对象传入进去。从而让当前bean的依赖有值可用。
                简单的说就是:缺什么,传什么。
           注入的方式:
                通过spring的配置文件(或者注解)来完成的。
                目的就是:不仅让spring管理对象的创建,还让spring管理对象间的依赖关系
           spring中依赖注入的配置方式:
                第一种方式:构造函数注入        用的较少
                第二种方式:set方法注入         绝大多数都会使用set方法注入
           spring中依赖注入支持的数据分类:
                第一种:基本类型和String类型
                第二种:ioc容器中包含的其他bean类型
                第三种:复杂类型(集合类型)

    -->
		
    <!--配置service交给spring来管理-->
    <!--构造函数注入
        涉及的标签:
            constructor-arg
        标签出现位置:
            写在bean标签内部
        标签的属性:
            type :指定在构造函数中的类型
            index:指定在构造函数中的位置
            name:指定在构造函数中的名称
            value:指定基本类型和String类型的数据内容
            ref:指定引用其他bean类型的id。
    -->
    <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
        <constructor-arg name="driver" value="com.mysql.jdbc.Driver"></constructor-arg>
        <constructor-arg name="port" value="3306"></constructor-arg>
        <constructor-arg name="date" ref="now"></constructor-arg>
    </bean>

    <bean id="now" class="java.util.Date"></bean>
</beans>

3.4.3set方法注入

package com.itheima.service.impl;

import com.itheima.service.UserService;

import java.util.*;

/**
 * 用户的业务层实现类
 * 用于演示set方法注入
 */
public class UserServiceImpl2 implements UserService {

    private String driver;//基本类型和String的演示
    private int port;//基本类型和String的演示

    private Date date;//其他bean类型的演示

    private String[] myStrs;//数组类型的演示
    private List<String> myList;//list集合类型的演示
    private Set<String> mySet;//set集合类型的演示
    private Map<String,String> myMap;//map集合的类型的演示
    private Properties myProps;//properties类型的演示

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    @Override
    public void saveUser() {
        System.out.println(driver);
        System.out.println(port);
        System.out.println(date);
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }
}
<!--set方法注入
        涉及的标签:
            property
        标签出现的位置
           bean标签内部
        标签的属性
            name:指定的是set方法的名称
            value:指定基本类型和String类型的数据内容
            ref:指定引用其他bean类型的id。
    -->
    <bean id="userService2" class="com.itheima.service.impl.UserServiceImpl2">
        <property name="driver" value="com.itheima.test"></property>
        <property name="port" value="8080"></property>
        <property name="date" ref="now"></property>
    </bean>

3.4.4注入集合属性

 <!--复杂类型注入:
                涉及的标签
                    array                   ***
                    list
                    set
                    map
                    props                  ***
                标签出现的位置:
                    都是写在property标签的内部

                结论:
                   集合类型的结构相同,标签可以互换
        -->
        <property name="myStrs">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <property name="myList">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <property name="mySet">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>

        <property name="myMap">
            <props>
                <prop key="propKey1">propValue1</prop>
                <prop key="propKey2">propValue2</prop>
                <prop key="propKey3">propValue3</prop>
            </props>
        </property>

        <property name="myProps">
            <map>
                <entry key="key1" value="value1"></entry>
                <entry key="key2" value="value2"></entry>
                <entry key="key3" value="value3"></entry>
            </map>
        </property>

3.5多配置文件使用

* 我们现在的配置都集中配在了一个applicationContext.xml文件中,这样会使这个文件很难维护。
* 针对这个问题,Spring给我们提供了两种解决方案:
	1. 同时引入多个配置文件
	2. 引入一个主配置文件,在主配置文件中引入其他配置文件

* 注意:
	1. 同一个xml文件中不允许出现相同名称的bean,如果出现会报错
	2. 多个xml文件如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载,所以尽量保证bean的名称是唯一的

第四章 JdbcTemplate(会用)

4.1JdbcTemplate介绍

* JdbcTemplate是Spring提供的持久层技术,用于操作数据库,它底层封装了JDBC技术。
* 核心类:
	JdbcTemplate  用于执行增删改查的SQL语句
	RowMapper     这是一个接口,主要作用是将数据库返回的记录封装进实体对象
* 核心方法:
	update  用来执行增、删、改语句
	query/queryForObject用来执行查询语句
//创建一个JdbcTemplate对象,用来执行增删改查, 需要给一个数据源
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

//update方法,用于执行增删改语句
//第一个参数:sql语句   后面的参数:sql语句中的所需要的的值
jdbcTemplate.update("insert into account value(null,?,?)",1,2);

//query或者queryForObject方法,用于执行查询语句
//query 用于查询多条记录,返回一个集合   queryForObject用于查询一条记录,返回一个实体
//第一个参数:sql语句   第二个参数:封装返回值   后面的参数:sql语句中的所需要的的值
jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); 
jdbcTemplate.queryForObject("select * from account where id = ?",  new BeanPropertyRowMapper<Account>(Account.class), 1);

4.2JdbcTemplate使用

使用JdbcTemplate完成对数据库的增删改查

准备数据环境

create table account(
	id int primary key auto_increment,
	name varchar(100) not null unique,
	money float(10,2)
)

4.2.2 创建模块,引入依赖

在这里插入图片描述

 <dependencies>
        <!--引入spring的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.12</version>
        </dependency>

        <!--引入spring的jdbc的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.12</version>
        </dependency>

        <!--引入mysql数据库的驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--引入阿里巴巴的druid连接池(数据源)-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <!--lombok的坐标-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
        </dependency>

        <!--junit的依赖坐标-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

4.2.3 创建实体类

package com.itheima.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

/**
 * 账户的实体类
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Account implements Serializable {

    private Integer id;
    private String name;
    private Float money;
}

4.2.4 编写配置文件

<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--引入外部的properties文件
        context名称空间:context:
        property-placeholder 他是引入外部properties文件的标签。
        location属性:指定properties文件的位置
            【classpath:】spring配置文件独有的,在别的配置文件中不支持。代表的是类路径下。
    -->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
		
	<!--配置JdbcTemplate-->
    <bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置DataSource-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
</beans>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_ee393
jdbc.username=root
jdbc.password=1234

4.2.5 测试

package com.itheima.test;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * JdbcTemplate的入门案例
 */
public class JdbcTemplateDemo1 {

    /**
     * JdbcTemplate的使用:
     *     1.创建对象
     *     2.调用方法完成对数据库的操作
     *          update  增删改方法都执行JdbcTemplate的update方法
     *          query   查询方法都执行JdbcTemplate的query方法
     * @param args
     */
    public static void main(String[] args) {
        //1.创建JdbcTemplate的对象
        JdbcTemplate jt = new JdbcTemplate();
        //2.为JdbcTemplate准备数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_ee393");
        dataSource.setUsername("root");
        dataSource.setPassword("1234");
        //3.把数据源传给JdbcTemplate
        jt.setDataSource(dataSource);
        //4.保存一个账户
        String sql = "insert into account(name,money)values(?,?);";//JDBC的参数占位符(不是mybatis)
        jt.update(sql,"test",1000f);
    }
}

package com.itheima.test;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * JdbcTemplate的入门案例
 *      使用Spring的IoC容器
 */
public class JdbcTemplateDemo2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //1.读取核心配置文件,创建ioc容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.根据id获取JdbcTemplate对象
        JdbcTemplate jt = ac.getBean("jt", JdbcTemplate.class);
        //3.保存一个账户
        String sql = "insert into account(name,money)values(?,?);";//JDBC的参数占位符(不是mybatis)
        jt.update(sql,"ioc",2000f);
    }
}

package com.itheima.test;

import com.itheima.domain.Account;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

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

/**
 * JdbcTemplate的入门案例
 *      使用JdbcTemplate完成增删改查
 */
public class JdbcTemplateDemo3 {

    private JdbcTemplate jt = null;

    @Before
    public void init(){
        //1.读取核心配置文件,创建ioc容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.根据id获取JdbcTemplate对象
        jt = ac.getBean("jt", JdbcTemplate.class);
    }
    /**
     *   JdbcTemplate的update(String sql,Object...params);
     *      增删改方法都使用这个update方法
     *      第一个参数:要执行的SQL语句
     *      第二个参数:执行语句所需的参数
     */


    /**
     * 测试保存
     */
    @Test
    public void testSave(){
        //3.保存一个账户
        String sql = "insert into account(name,money)values(?,?);";//JDBC的参数占位符(不是mybatis)
        jt.update(sql,"ioc",2000f);
    }

    /**
     * 测试更新
     */
    @Test
    public void testUpdate(){
        jt.update("update account set name=? , money=? where id=?","ee393期",50000f,1);
    }


    @Test
    public void testDelete(){
        int res = jt.update("delete from account where id = ?", 2);
        System.out.println("影响数据库记录的行数:"+res);
    }

    /**
     * JdbcTemplate的query(String sql,RowMapper rowMapper,Object...params)方法
     *    该方法只能用于查询,他有3个参数
     *    第一个参数:要执行的SQL语句
     *    第二个参数:指定查询结果的封装规则。
     *                RowMapper他是一个接口,我们可以自己写实现类
     *                通常情况下我们都会封装到实体类中,只要实体类的属性与数据库表中字段一致,就可以使用Spring提供的
     *                Spring提供的类:BeanPropertyRowMapper
     *    第三个参数:执行sql语句所需的参数
     *
     */

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        List<Account> accounts = jt.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

    /**
     * 测试根据id查询
     */
    @Test
    public void testFindById(){
        List<Account> accounts = jt.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class),1);
        if(accounts != null && accounts.size() > 0 ){
            System.out.println(accounts.get(0));
        }
    }
}

第五章 综合练习(重点)

使用Spring和JdbcTemplate完成对数据库的crud操作

  • 持久层 JdbcTemplate

  • 业务层 Spring

  • 表示层 单元测试

5.1 创建模块,引入依赖

在这里插入图片描述

 <dependencies>
        <!--引入spring的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.12</version>
        </dependency>

        <!--引入spring的jdbc的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.12</version>
        </dependency>

        <!--引入mysql数据库的驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--引入阿里巴巴的druid连接池(数据源)-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <!--lombok的坐标-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
        </dependency>

        <!--junit的依赖坐标-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

5.2 创建实体类

package com.itheima.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

/**
 * 账户的实体类
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Account implements Serializable {

    private Integer id;
    private String name;
    private Float money;
}

5.3创建dao层接口

package com.itheima.dao;

import com.itheima.domain.Account;

import java.util.List;

/**
 * 账户的持久层接口
 */
public interface AccountDao {

    /**
     * 查询所有账户
     * @return
     */
    List<Account> findAll();

    /**
     * 根据id查询账户
     * @param id
     * @return
     */
    Account findById(Integer id);

    /**
     * 保存
     * @param account
     */
    void save(Account account);

    /**
     * 更新
     * @param account
     */
    void update(Account account);

    /**
     * 删除
     * @param id
     */
    void delete(Integer id);
}

5.4创建dao层实现类

package com.itheima.dao.impl;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements AccountDao {

    private JdbcTemplate jdbcTemplate;

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

    @Override
    public List<Account> findAll() {
        return jdbcTemplate.query("select * from account ",new BeanPropertyRowMapper<Account>(Account.class));
    }

    @Override
    public Account findById(Integer id) {
        List<Account> accounts = jdbcTemplate.query("select * from account where id = ? ", new BeanPropertyRowMapper<Account>(Account.class), id);
        return (accounts != null && accounts.size() == 1) ? accounts.get(0) : null ;
    }

    @Override
    public void save(Account account) {
        jdbcTemplate.update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
    }

    @Override
    public void update(Account account) {
        jdbcTemplate.update("update account set name=?,money=? where id = ?",account.getName(),account.getMoney(),account.getId());
    }

    @Override
    public void delete(Integer id) {
        jdbcTemplate.update("delete from account where id = ?",id);
    }
}

5.5 创建service层接口

package com.itheima.service;


import com.itheima.domain.Account;

import java.util.List;

/**
 * 账户的业务层接口
 */
public interface AccountService {

    /**
     * 查询所有账户
     * @return
     */
    List<Account> findAll();

    /**
     * 根据id查询账户
     * @param id
     * @return
     */
    Account findById(Integer id);

    /**
     * 保存
     * @param account
     */
    void save(Account account);

    /**
     * 更新
     * @param account
     */
    void update(Account account);

    /**
     * 删除
     * @param id
     */
    void delete(Integer id);
}

5.6 创建service层实现类

package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;

import java.util.List;

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public List<Account> findAll() {
        return accountDao.findAll();
    }

    @Override
    public Account findById(Integer id) {
        return accountDao.findById(id);
    }

    @Override
    public void save(Account account) {
        accountDao.save(account);
    }

    @Override
    public void update(Account account) {
        accountDao.update(account);
    }

    @Override
    public void delete(Integer id) {
        accountDao.delete(id);
    }
}

5.7 加入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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--引入外部properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
</beans>
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <!--配置账户的持久层-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!--注入JdbcTemplate-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

</beans>
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <!--配置账户的业务层-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <!--注入dao-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>


</beans>
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <!--引入spring的配置文件-->
    <import resource="classpath:applicationContext-dao.xml"></import>
    <import resource="classpath:applicationContext-jdbc.xml"></import>
    <import resource="classpath:applicationContext-service.xml"></import>

</beans>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_ee393
jdbc.username=root
jdbc.password=1234

5.8 测试

package com.itheima.test;

import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

/**
 * 测试spring的ioc配置
 */
public class AccountServiceTest {

    private AccountService accountService;

    @Before
    public void init(){
        //1.获取Ioc容器
        //spring多配置文件开发之:并列关系
//        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-dao.xml",
//                                                                                     "classpath:applicationContext-service.xml",
//                                                                                     "classpath:applicationContext-jdbc.xml");
        //spring多配置文件开发之:主从关系   如果只是单独使用spring,主从关系的配置方式更多一些。(后面用了spring-boot之后,就不区分,只有一个配置文件)
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        //2.根据id获取bean
        accountService = ac.getBean("accountService", AccountService.class);
    }

    @Test
    public void testFindAll(){
        List<Account> accounts = accountService.findAll();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

    @Test
    public void testFindById(){
        Account account = accountService.findById(1);
        System.out.println(account);
    }

    @Test
    public void testSave(){
        Account account = new Account();
        account.setName("测试ioc");
        account.setMoney(10000f);
        accountService.save(account);
    }

    @Test
    public void testUpdate(){
        Account account = accountService.findById(3);
        account.setName("testioc");
        account.setMoney(5678f);
        accountService.update(account);
    }

    @Test
    public void testDelete(){
        accountService.delete(3);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值