Spring官网
菜鸟教程-Spring基础知识汇总 Java开发必看
常用插件
xml智能提示
经典三层框架有这些
web层
service层(业务层)
dao层(持久层)
Spring是service层框架,很重要,讲多少用多少
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jn5yNirD-1589804546842)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569230492056.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UpM6RXIg-1589804546845)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569230339444.png)]
需要弄一下 log4j.properties的配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lnCAlCnH-1589804546847)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569330959479.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Cokmdbk-1589804546849)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569232616073.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tQRKlxf-1589804546852)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569232929356.png)]
提供UserService接口和实现类
获得UserService实现类的实例
定义接口
package com.itheima.a_ioc;
public interface UserService {
public void addUser();
}
package com.itheima.a_ioc;
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println(a_ico add user);
}
}
XML需要点选design来看代码,别用Open with Text Editer,那样就没有高亮了。
applicationContext.xml
schema约束
<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">
<bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl">bean>
beans>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wUqDTbKw-1589804546854)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569238062721.png)]
构造方法的 普通类型 属性注入用
构造方法的 对象类型 属性注入用
set方法的 普通类型 属性注入用
set方法的 对象类型 属性注入用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7BJwHLkD-1589804546856)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569389775684.png)]
前提是必须有IOC的环境
is a :是一个,继承
has a :有一个,成员变量,依赖
class B{
private A a; //B类依赖A类
}
依赖:一个对象需要使用另一个对象
注入:通过setter方法进行另一个对象实例设置
class B{
private A a;// B类依赖A类
}
这两个图非常重要,方便理解IoC和DI,解耦与耦合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbfjgGni-1589804546857)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569246052188.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o5QNEmM3-1589804546860)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569246503730.png)]
目标类
配置文件
测试
要使用p名称空间,需要修改头部的xmlns
beans
变p
,然后前缀改成xmlns:
不用p空间就要把
xmlns:
那一行删去,不然会有问题
xmlns="http://www.springframework.org/schema/beans"
xmlns:="http://www.springframework.org/schema/p"
<bean id="car2" class="com.binyu.spring.demo4.Car2" p:name="奇瑞qq" p:price="30000">bean>
<bean id="employee" class="com.binyu.spring.demo4.Employee" p:name="王东" p:car2-ref="car2">bean>
#{SpEL}
使用前,要确认xmlns:
已经清除
<bean id="car2" class="com.binyu.spring.demo4.Car2">
<property name="name" value="#{'三蹦子'}">property>
<property name="price" value="#{3000}">property>
bean>
<bean id="employee" class="com.binyu.spring.demo4.Employee">
<property name="name" value="#{'赵洪'}">property>
<property name="car2" value="#{car2}">property>
bean>
<bean id="carInfo" class="com.binyu.spring.demo4.CarInfo">bean>
<bean id="car2" class="com.binyu.spring.demo4.Car2">
<property name="name" value="#{carInfo.name}">property>
<property name="price" value="#{carInfo.calculatorPrice()}">property>
bean>
package com.binyu.spring.demo5;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 集合属性的注入
* @author Dong Binyu
*
*/
public class CollectionBean {
private String[] arrs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
public void setArrs(String[] arrs) {
this.arrs=arrs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String,String> map) {
this.map = map;
}
@Override
public String toString() {
return "CollectionBean [arrs=" + Arrays.toString(arrs) + ", list=" + list + ", set=" + set + ", map=" + map
+ "]";
}
}
<bean id="collection"
class="com.binyu.spring.demo5.CollectionBean">
<property name="arrs">
<list>
<value>董滨雨value>
<value>李铭霞value>
<value>在一起value>
<value>真好看value>
list>
property>
<property name="list">
<list>
<value>大学里value>
<value>谈恋爱value>
<value>在一起value>
<value>真好看value>
list>
property>
<property name="set">
<set>
<value>set1value>
<value>set2value>
<value>set3value>
<value>set4value>
set>
property>
<property name="map">
<map>
<entry key="aaa" value="111">entry>
<entry key="bbb" value="222">entry>
<entry key="ccc" value="333">entry>
map>
property>
bean>
package com.binyu.spring.demo5;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo5 {
@Test
public void demo1() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionBean collectionBean=(CollectionBean) applicationContext.getBean("collectionBean");
System.out.println(collectionBean);
}
}
Spring的工厂类的结构图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vBRNZuKl-1589804546861)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml11952\wps1.jpg)]
BeanFactory:老版本的工厂类
ApplicationContext:新版本的工厂类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnCjY3xw-1589804546863)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569372714504.png)]
一个xml能被一个DTD约束,但是可以被多个schema约束的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A2dN1eVv-1589804546865)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569311744329.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XMp1fJrQ-1589804546866)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569312103651.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v26LIbHs-1589804546867)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569312239368.png)]
Bean标签id和name的配置
id
:使用了约束中的唯一约束。里面不能出现特殊字符name
:没有使用唯一约束(理论上可以重复,但是实际开发中不允许)。里面可以出现特殊字符
class
:实例的类的全路径Bean的生命周期配置【了解】
init-method
:Bean被初始化执行的方法destroy-method
:Bean被销毁时执行的方法(Bean是单例创建,工厂关闭)Bean的作用范围的配置【重点】
scope
:Bean的作用范围
singleton
:默认的,spring会采用单例模式创建这个对象(当容器创建时活着,当容器销毁时死亡)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Te4vqzvj-1589804546870)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569389214451.png)]
prototype
:多例模式【Structs2和Spring整合的时候要用到】(当使用对象时活着,当对象长时间不用才会回收)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25T8flH2-1589804546872)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569389126142.png)]
request
:应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中session
:应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中globalsession
:应用在web项目中,必须在porlet环境下使用。但是如果没有这种环境,相当于session单例模式:不管有多少次程序调用,只会new一次。每次用的只是一个实例
多例模式:用一次就new一次
porlet环境:子域名免登录,比如百度中的百度云,百度百科
配置两个xml
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
在一个xml中引用另一个xml
<import resource="applicationContext2.xml"/>
@Import("ApplicationContext2.xml")
@Import(ApplicationContext2.class)
用了struts2框架,没太懂!!
JSP 它使用JSP标签在HTML网页中插入Java代码
搭建开发环境
创建数据库和表
创建一个web项目,引入jar包
引入struts2开发的jar包
引入struts2的配置文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjcBD69p-1589804546873)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569587482493.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5BKW9n95-1589804546875)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569587536420.png)]
引入页面
编写action
配置action
修改页面提交到action
编写action的save方法
引入spring的环境
将Service交给Spring
在Action中调用Service
编写DAO并完成配置
在Service中使用DAO
注解开发:不需要配置文件
创建web项目,引入6+1(aop的jar包)
创建applicationContext.xml
,并引入context约束(之前引入的是bean约束)
实现接口和实现类
开启Spring的组件扫描
<context:component-scan base-package="com.binyu.demo1"/>
@Component("userDao")// 相当于
public class UserDAOImpl implements UserDAO {
@Value("注解牛逼!")
String name;
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserDAO"+name);
}
}
@Component
:组件其实就是控制反转,将类交给Spring管理
@Controller
:web层@Service
:service层@Repository
:DAO层其实就是依赖注入
@Value
:设置普通属性的值
@Autowired
:设置对象类型的属性的值,
@Qualifier
和@Autowired
一起使用@Resource
:完成对象类型的属性注入,按照名称完成属性注入,@Resource(name="xxx")
生命周期相关的注解
这两个注解目前使用不了,原因不明
@PostConstruct
:初始化方法@PreDestroy
:销毁方法Bean作用范围的注解
@Scope
:作用范围
singleton
:默认单例prototype
:多例request
session
globalsession
@Configuration
:指定当前类是一个配置类
@ComponentScan(base-package="")
:通过注解指定spring在创建容器时要扫描的包,等同于
@Bean
:用于把当前方法的返回值作为bean对象存入spring的容器中。name和value是它的两个属性,value不指定时默认是方法名。
@PropertiesSource(classpath:jdbcConfig.properties)
:用于加载配置文件
导入spring-test 的jar包
@Runwith(SpringJunit4ClassRunner.class)
@ContextConfiguration(classpath:applicationcontext.xml)
Spring中基于AOP的XML架构
Spring AOP基于XML配置的切面
AOP:面向切面编程,是OOP开发的拓展和延伸,解决OOP开发遇到的问题
底层实现是用的 JDK动态代理和Cglib动态代理的自动切换
方便了 方法增强和拓展
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iuN5ga6C-1589804546877)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569742736079.png)]
AOP可以用来:日志记录、审计、声明式事务、安全性和缓存等
动态代理的部分我又没听懂~
AspectJ是一个AOP的框架,Spring后来的版本引入AspectJ作为AOP的开发
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lIkt8HTC-1589804546880)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1569744167440.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ysQXj8Yb-1589804546881)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570418961080.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-flWwKu4U-1589804546883)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570419442987.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adCQI4pi-1589804546885)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570420173194.png)]
Spring整合单元测试的jar包是
spring-test-4.2.4.RELEASE.jar
package com.binyu.demo1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDemo {
@Autowired
@Qualifier("productDao")
private ProductDao productDao;
@Test
public void demo1() {
productDao.save();
productDao.update();
productDao.find();
productDao.delete();
}
@Test
public void demo2() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
ProductDao productDao=(ProductDao) applicationContext.getBean("productDao");
productDao.save();
productDao.update();
productDao.find();
productDao.delete();
}
}
package com.binyu.demo1;
/**
* 切面类
* @author Dong Binyu
*
*/
public class MyAspectXML {
public void checkPri() {
System.out.println("这是权限校验方法。。。");
}
}
<bean id="myAspectXML" class="com.binyu.demo1.MyAspectXML">bean>
<aop:config>
<aop:pointcut
expression="execution(* com.binyu.demo1.ProductDaoImpl.save(..))"
id="pointcut1" />
<aop:aspect ref="myAspectXML">
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
aop:aspect>
aop:config>
execution切入点表达式
的写法SpringAOP切入点表达式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CCggt8V1-1589804546886)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570426284560.png)]
applicationContext.xml
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
beans>
编写目标类并配置
编写切面类并配置
使用注解的AOP对象目标类进行增强
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
package com.binyu.demo1;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* 切面类:注解的切面类
*
* @author Dong Binyu
*
*/
@Aspect
public class MyAspectAnno {
@Before(value="execution(* com.binyu.demo1.OrderDao.save(..))")
public void before() {
System.out.println("前置增强-------");
}
}
package com.binyu.demo1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDemo {
@Autowired
@Qualifier(value = "orderDao")
private OrderDao orderDao;
@Test
public void demo1() {
orderDao.save();
orderDao.update();
orderDao.find();
orderDao.delete();
}
}
@Before
前置通知:在目标方法执行之前进行操作@Before(value="execution(* com.binyu.demo1.OrderDao.save(..))")
public void before() {
System.out.println("前置增强-------");
}
@AfterReturning
后置通知:在目标方法执行之后进行操作@AfterReturning(value="execution(* com.binyu.demo1.OrderDao.delete(..))",returning = "result")
// 用returning拿到切面目标类方法的返回值
public void afterReturning(Object result) {
System.out.println("后置增强----------"+result);
}
@Around
环绕通知:在目标方法执行之前和之后进行操作// 环绕通知
@Around(value="execution(* com.binyu.demo1.OrderDao.update(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前通知-------");
Object obj=joinPoint.proceed();
System.out.println("环绕后通知-------");
return obj;
}
@AfterThrowing
异常抛出通知:出现异常时候,进行的操作// 异常抛出通知
@AfterThrowing(value="execution(* com.binyu.demo1.OrderDao.find(..))",throwing = "e")
public void afterThrowing(Throwable e) {
System.out.println("异常抛出通知。。。"+e.getMessage());
}
注意:如果find方法没有异常,则不会调用该切面类的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TUoZ7hkn-1589804546888)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570428840300.png)]
@After
最终通知:无论代码是否有异常,都进行操作// 最终通知
@After(value="execution(* com.binyu.demo1.OrderDao.find(..))")
public void after() {
System.out.println("这是最终通知----");
}
@Pointcut
package com.binyu.demo1;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 切面类:注解的切面类
*
* @author Dong Binyu
*
*/
@Aspect
public class MyAspectAnno {
// 前置通知
// @Before(value="execution(* com.binyu.demo1.OrderDao.save(..))")
@Before(value="MyAspectAnno.pointcut2()")
public void before() {
System.out.println("前置增强-------");
}
@AfterReturning(value="MyAspectAnno.pointcut4()",returning = "result")
// 用returning拿到切面目标类方法的返回值
public void afterReturning(Object result) {
System.out.println("后置增强----------"+result);
}
// 切入点注解
@Pointcut(value="execution(* com.binyu.demo1.OrderDao.find(..))")
private void pointcut1() {};
@Pointcut(value="execution(* com.binyu.demo1.OrderDao.save(..))")
private void pointcut2() {};
@Pointcut(value="execution(* com.binyu.demo1.OrderDao.update(..))")
private void pointcut3() {};
@Pointcut(value="execution(* com.binyu.demo1.OrderDao.delete(..))")
private void pointcut4() {};
}
如果目标类实现了接口,Spring底层使用JDK动态代理
如果目标类没有实现接口,Spring底层使用cglib动态代理
Spring是EE开发的一站式框架,有EE开发的每层的解决方案,Spring对持久层也提供了解决方:ORM模块和JDBC模板
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-83KerrCH-1589804546889)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570432758263.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hj819ilk-1589804546891)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570433298075.png)]
create database spring_day03;
use spring_day03;
create table account(
id int primary key auto_increment,
name varchar(20),
money double);
package com.binyu.jdbc.demo1;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class JdbcDemo1 {
@Test
public void demo1() {
// jdbc模板的使用类似于Dbutils
// 创建连接池
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_day03");
dataSource.setUsername("root");
dataSource.setPassword("root");
// 创建jdbc模板
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update("insert into account values(null,?,?)","陈冠希",100000d);
}
}
mysql> select * from account;
+----+-----------+--------+
| id | name | money |
+----+-----------+--------+
| 1 | 陈冠希 | 100000 |
+----+-----------+--------+
1 row in set (0.00 sec)
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql:///spring_day03">property>
<property name="username" value="root">property>
<property name="password" value="root">property>
bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
beans>
package com.binyu.jdbc.demo1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
@Autowired
@Qualifier(value="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void demo2() {
jdbcTemplate.update("insert into account values(null,?,?)","王宝强",10000d);
}
}
因为是Spring4的缘故,此时会报错,需要引入aop的jar包!!!
Spring3不报错。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S89eOZAo-1589804546894)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570435837305.png)]
运行了三次,所以出现了这种情况
mysql> select * from account;
+----+-----------+--------+
| id | name | money |
+----+-----------+--------+
| 1 | 陈冠希 | 100000 |
| 2 | 王宝强 | 10000 |
| 3 | 王宝强 | 10000 |
| 4 | 王宝强 | 10000 |
+----+-----------+--------+
4 rows in set (0.00 sec)
DBCP连接池的属性和Spring内置连接池属性相同
C3P0连接池的属性和前面两个连接池不同
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1pvxI3N-1589804546895)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570436597937.png)]
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql:///spring_day03">property>
<property name="username" value="root">property>
<property name="password" value="root">property>
bean>
编写测试类
略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nm6JQK3e-1589804546896)(C:\Users\dby\AppData\Roaming\Typora\typora-user-images\1570438347016.png)]
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"
value="com.mysql.jdbc.Driver">property>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03">property>
<property name="user" value="root">property>
<property name="password" value="root">property>
bean>
mysql> select * from account;
+----+-----------+--------+
| id | name | money |
+----+-----------+--------+
| 1 | 陈冠希 | 100000 |
| 2 | 王宝强 | 10000 |
| 3 | 王宝强 | 10000 |
| 4 | 王宝强 | 10000 |
| 5 | 李如花 | 10000 |
| 6 | 邓紫棋 | 10000 |
+----+-----------+--------+
6 rows in set (0.01 sec)
jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_day03
jdbc.username=root
jdbc.password=root
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"
value="${jdbc.driverClass}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
添加操作
上面已经做了
修改操作
// 修改操作
@Test
public void demo2() {
jdbcTemplate.update("update account set name=?,money=? where id=6","董滨雨",2000.2d);
}
// 删除操作
@Test
public void demo3() {
jdbcTemplate.update("delete from account where id=?",6);
}
mysql> select * from account;
+----+-----------+--------+
| id | name | money |
+----+-----------+--------+
| 1 | 陈冠希 | 100000 |
| 2 | 王宝强 | 10000 |
| 3 | 王宝强 | 10000 |
| 4 | 王宝强 | 10000 |
| 5 | 李如花 | 10000 |
| 7 | 邓紫棋 | 10000 |
+----+-----------+--------+
6 rows in set (0.00 sec)
// 查询操作
@Test
public void demo4() {
String name=jdbcTemplate.queryForObject("select name from account where id=?", String.class,5);
System.out.println(name);
}
@Test
public void demo5() {
Long count=jdbcTemplate.queryForObject("select count(*) from account ", Long.class);
System.out.println(count);
}
package com.binyu.domain;
public class Account {
private Integer id;
private String name;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
// 查询然后封装到一个Account对象中
@Test
public void demo6() {
Account account=jdbcTemplate.queryForObject("select * from account where id=?",new MyRowMapper(),5);
System.out.println(account);
}
class MyRowMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account=new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
// 查询然后返回一个Account集合
@Test
public void demo7() {
List<Account> list = jdbcTemplate.query("select * from account", new MyRowMapper());
for (Account account : list) {
System.out.println(account);
}
}
控制台的输出:
Account [id=1, name=陈冠希, money=100000.0]
Account [id=2, name=王宝强, money=10000.0]
Account [id=3, name=王宝强, money=10000.0]
Account [id=4, name=王宝强, money=10000.0]
Account [id=5, name=李如花, money=10000.0]
Account [id=7, name=邓紫棋, money=10000.0]
逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败
Read uncommitted
:未提交读,任何读问题解决不了Read committed
:已提交读,解决脏读,但是不可重复读和虚读有可能发生。(Oracle使用)Repeatable read
:重复读,解决脏读和不可重复度,但是虚读有可能发生。(MySql使用)Serializable
:解决所有读问题,但是不允许事务并发。安全但是效率很低。PlatformTransactionManager
平台事务管理器
TransactionDefinition
事务定义信息
TransactionStatus
事务状态
三个API的关系如下:
Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理的过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中
主要用来解决 Service业务层方法相互调用的问题
Spring提供了七种事务的传播行为,一般用PROPAGATION_REQUIRED
保证多个操作在同一个事务中
保证多个操作不在同一个事务中
嵌套式事务
详见 com.binyu.tx.demo1
JdbcDaoSupport类
<bean id="accountService" class="com.binyu.tx.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao">property>
bean>
<bean id="accountDao" class="com.binyu.tx.demo1.AccountDaoImpl">bean>
在Dao中编写扣钱和加钱方法
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"
value="${jdbc.driverClass}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
在Dao中注入JDBC模板
方法一
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
方法二
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money = money - ? where name = ?", money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money = money + ? where name = ?", money ,to);
}
}
如果没有事务管理,一旦业务层出现问题,数据库就会被误操作
<bean id="accountService"
class="com.binyu.tx.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao">
property>
<property name="transactionTemplate" ref="transactionTemplate">
property>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">
property>
bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager">bean>
package com.binyu.tx.demo1;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
* 转账的业务层的实现类
* @author Dong Binyu
*
*/
public class AccountServiceImpl implements AccountService {
// 注入Dao
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
// 注入事务管理的模板
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
/**
* from:转出账号
* to:转入账号
* money:转帐金额
*/
@Override
public void transfer(final String from, final String to,final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
// 这两个操作需要事务管理
accountDao.outMoney(from, money);
// int i=1/0;
accountDao.inMoney(to,money);
}
});
}
}
l 第一步:引入aop的开发包
l 第二步:恢复转账环境
l 第三步:配置事务管理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IziLSbbH-1589804546898)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps1.jpg)]
l 第四步:配置增强
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BmQke1Tc-1589804546900)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps2.jpg)]
l 第五步:AOP的配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lx5VZdJJ-1589804546901)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps3.jpg)]
l 测试
@Transactional
l 第一步:引入aop的开发包
l 第二步:恢复转账环境
l 第三步:配置事务管理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DGYXMOTX-1589804546902)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps4.jpg)]
l 第四步:开启注解事务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RlQ2mfZV-1589804546903)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps5.jpg)]
l 第五步:在业务层添加注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVwSc4wy-1589804546905)(file:///C:\Users\dby\AppData\Local\Temp\ksohtml137472\wps6.jpg)]