前提
: 我们用了Mybatis时,已经不需要再使用其他的持久层框架了。用了mybatis之后,我们只需要写持久层接口以及sql语句即可。
但是为了讲解spring中的事务,我们把JdbcTemplate拿出来讲,使用JdbcTemplate需要编写持久层实现类。
此时有两个目的:
第一个:通过JdbcTemplate去铺垫Spring第三天课程的事务控制。(配置的方式实现)
第二个:通过JdbcTemplate去更加深入掌握依赖注入思想(今天就说明明白)
spring的课程安排
:
课程时长: 共5天。其中spring框架3天,springmvc框架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
(全栈式)轻量级开源框架,以IoC
(Inverse Of Control
:反转控制)和AOP
(Aspect 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 体系架构图
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基础代码编写
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要点分析
-
SpringIOC容器启动过程中要做哪些操作
![[]](https://img-blog.csdnimg.cn/8a3f7b3154cc4f1ab225b584f0f76db4.png)
-
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创建对象的三种方式(了解)
我们常用的创建对象的方式有三种:
- 直接使用new关键字创建
- 使用静态工厂创建
- 使用实例化工厂创建
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);
}
}