把别人编写的类交给spring管理
在外部创建一个jdbc.properties配置文件 这个里面配置各个数据库的信息
在spirng的配置文件中,加载外部的jdbc.properties文件
<context:property-placeholder location="classpath:jdbc.properties"/>
通过spirng的ioc和di设定连接池的核心对象以及对象的核心属性
ps: ${} 是spring提供的的表达式 针对的就是spring加载了properties之后的数据
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
别人的类还用xml,自己的类都用注解
导包 spring-aop.jar
开启扫描器
<context:component-scan base-package="cn.dmdream">context:component-scan>
条件: 注解类
package cn.dmdream.springconfig;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration // 表示该类是一个注解类
@ComponentScan(basePackages="cn.dmdream") //
@PropertySource(value="classpath:jdbc.properties")//
//@Import(value = {DataSourceconfig.class})
public class SpringConfig
{
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
// 自己创建c3p0连接池 给spring容器
@Bean(name="c3p0") //
public DataSource createDataSourceC3p0() throws Exception
{
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}
// 4.3以前 要给spring配置一个解析器 来解析 ${}
@Bean
public static PropertySourcesPlaceholderConfigurer createPropertySourcesPlaceholderConfigurer()
{
return new PropertySourcesPlaceholderConfigurer();
}
}
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://cloud.dmdream.cn:3306/hibernate
jdbc.username=root
jdbc.password=1234
加载不是配置文件了 而是注解类
测试类Demo代码
package cn.dmdream.test;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import cn.dmdream.springconfig.SpringConfig;
public class SpringConfigTest
{
@Test
public void test() throws SQLException
{
// 加载注解类
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
/* UserService userService=(UserService)context.getBean("userService");
userService.save();*/
DataSource ds =(DataSource)context.getBean("c3p0");
Connection con = ds.getConnection();
System.out.println(con);
}
}
AOP: 面相切面编程思想
简单理解: 将一些共性的内容进行抽取,在需要用到的地方,以动态代理的方式进行插入
在不修改源码的基础上,还能对源码进行前后的增强
底层的技术: 动态代理
spring就是把动态代理进行层层封装 诞生出了aop思想
举例
两种动态代理的方式
不用导包,jdk提供好了
proxy
条件: 目标类必须得有接口
@Test
public void test2()
{
// 目标类
final UserImpl user=new UserImpl();
// jdk的动态代理
// 参数一: 和目标类一样的类加载器
// 参数二: 和目标类一样的接口
// 参数三: 增强的业务
User userproxy=(User)Proxy.newProxyInstance(
user.getClass().getClassLoader(),
user.getClass().getInterfaces(),
new InvocationHandler() {
@Override //增强的业务
// 参数一: 固定值
// 参数二: 要增强的方法 (原有的方法)
// 参数三: 方法运行时候需要的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName()))
{
// 让原有方法执行
// 本身应该调用这个方法的对象
System.out.println("之前增强了...");
method.invoke(user, args);
System.out.println("之后增强了...");
}else
{
// 执行原来的方法
method.invoke(user, args);
}
return null;
}
});
userproxy.save(); // 只要执行,就会执行增强业务方法invoke方法,这个方法里面就是对save方法的增强
userproxy.delete(); // 只要执行,就会执行增强业务方法invoke方法,这个方法里面就是对delete方法的增强
}
User&Impl
package cn.dmdream.domain;
public interface User
{
public void save();
public void delete();
public void update();
public void find();
}
// 带接口的--为了演示jdk动态代理
public class UserImpl implements User
{
@Override
public void save() {
System.out.println("普通的保存方法...");
}
@Override
public void delete() {
System.out.println("普通的删除方法...");
}
@Override
public void update() {
System.out.println("普通的修改方法...");
}
@Override
public void find() {
System.out.println("普通的查询方法...");
}
}
第三方 单用它就必须导包
enhance
条件: 只要有一个目标类即可增强
@Test
public void test3()
{
// 目标类---没有接口
final Person person=new Person();
// CGLIB的方式
// 参数一: 目标类的字节码文件类型 因为用于继承
// 参数二: 增强的业务逻辑
Person p=(Person)Enhancer.create(Person.class,new MethodInterceptor() {
@Override
// 参数一: 代理对象的类型 固定值
// 参数二: 目标类要增强的方法
// 参数三: 方法运行时期需要的参数
// 参数四: 代理方法 忽略
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
if("delete".equals(method.getName()))
{
System.out.println("之前增强....");
method.invoke(person, args);
System.out.println("之后增强....");
}else
{
// 让原有方法执行
method.invoke(person, args);
}
return null;
}
});
p.delete(); // 执行了它 增强业务intercept方法也会执行 这个方法里面就是对delete的增强
p.find();// 执行了它 增强业务intercept方法也会执行 这个方法里面就是对find的增强
}
Person
package cn.dmdream.domain;
// 没有接口--为了演示cglib的动态代理
public class Person
{
public void save() {
System.out.println("普通的保存方法...");
}
public void delete() {
System.out.println("普通的删除方法...");
}
public void update() {
System.out.println("普通的修改方法...");
}
public void find() {
System.out.println("普通的查询方法...");
}
}
导包
开发步骤
需求: 对person中的save方法进行增强
确定目标类 (目标类中有切入点 —要被增强的方法)
<bean id="person" class="cn.dmdream.domain.Person">bean>
确定切面类 (里面有通知/增强 ----增强的那段代码方法)
<bean id="myAspect" class="cn.dmdream.aspectj.MyAspect">bean>
配置织入过程 (将增强方法和被增强方法进行结合)
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="beforeMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
<aop:after-returning method="aftereturningMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
<aop:after-returning method="aftereturningMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.save())" id="pointcut1"/>
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.delete())" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.Person.up*(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.*.find(..))" id="pointcut4"/>
<aop:before method="beforeMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut2"/>
<aop:around method="aroundMethod" pointcut-ref="pointcut3"/>
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut4"/>
<aop:after method="afterMethod" pointcut-ref="pointcut4"/>
aop:aspect>
aop:config>
AOP的xsd约束(完整版例子)
<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"
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">
<bean id="person" class="cn.dmdream.domain.Person">bean>
<bean id="myAspect" class="cn.dmdream.aspectj.MyAspect">bean>
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.save())" id="pointcut1"/>
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.delete())" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.Person.up*(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.*.find(..))" id="pointcut4"/>
<aop:before method="beforeMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut2"/>
<aop:around method="aroundMethod" pointcut-ref="pointcut3"/>
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut4"/>
<aop:after method="afterMethod" pointcut-ref="pointcut4"/>
aop:aspect>
aop:config>
beans>
方式一:不定义切入点
<bean id="person" class="cn.dmdream.domain.Person">bean>
<bean id="myAspect" class="cn.dmdream.aspectj.MyAspect">bean>
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="beforeMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
<aop:after-returning method="aftereturningMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
<aop:after-returning method="aftereturningMethod" pointcut="execution(void cn.dmdream.domain.Person.save())"/>
aop:aspect>
aop:config>
方式二:自定义切入点
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.save())" id="pointcut1"/>
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.delete())" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.Person.up*(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.dmdream.domain.*.find(..))" id="pointcut4"/>
<aop:before method="beforeMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut1"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut2"/>
<aop:around method="aroundMethod" pointcut-ref="pointcut3"/>
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut4"/>
<aop:after method="afterMethod" pointcut-ref="pointcut4"/>
execution(void cn.dmdream.domain.Person.save())
void cn.dmdream.domain. Person. save()
返回值 包名/子包名 类名 方法名
*: 代表所有
..: 代表上一层 或者是 方法参数的全匹配
* cn.dmdream.domain.Person.save(..)//最常用
* cn.dmdream.domain.Person.sa*(..)
* cn.dmdream.domain.*.*(..)
* cn.dmdream..*.*(..)
* cn.dmdream..Person.save(..)//最常用
切入点配置和织入过程详细见上面的配置文件
前置通知 在之前增强 权限拦截
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.save())" id="pointcut1"/>
<aop:before method="beforeMethod" pointcut-ref="pointcut1"/>
// 增强方法
public void beforeMethod()
{
System.out.println("-----beforeMethod-----");
}
后置通知 在之后增强 日志输出
<aop:pointcut expression="execution(void cn.dmdream.domain.Person.delete())" id="pointcut2"/>
<aop:after-returning method="aftereturningMethod" pointcut-ref="pointcut2"/>
// 增强方法
public void aftereturningMethod()
{
System.out.println("----aftereturningMethod---");
}
环绕通知 在之前和之后都增强 性能检测
<aop:pointcut expression="execution(* cn.dmdream.domain.Person.up*(..))" id="pointcut3"/>
<aop:around method="aroundMethod" pointcut-ref="pointcut3"/>
// 增强方法
public void aroundMethod(ProceedingJoinPoint pdp) throws Throwable // 正在要执行的原有方法
{
System.out.println("之前...");
// 原有方法执行一下
pdp.proceed(); // method.invoke();
System.out.println("之后...");
}
异常通知 catch{}
<aop:pointcut expression="execution(* cn.dmdream.domain.Person.up*(..))" id="pointcut3"/>
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut4"/>
// 增强方法
public void throwingMethod()
{
System.out.println("----throwingMethod----");
}
最终通知 finally {}
<aop:pointcut expression="execution(* cn.dmdream.domain.*.find(..))" id="pointcut4"/>
<aop:after method="afterMethod" pointcut-ref="pointcut4"/>
// 增强方法
public void afterMethod()
{
System.out.println("--不管你有没有异常,我都出来了---");
}
别人类用xml <–> 自己的类用注解
如何使用
导包 spring-aop.jar
开启注解扫描器
<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"
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">
<context:component-scan base-package="cn.dmdream">context:component-scan>
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
beans>
自己的类
使用注解替代aop织入的xml配置
确定谁是切面类 @Aspect
// 切面类--有增强方法
@Component("myAspect")
@Aspect
public class MyAspect{
...
}
切面类下面的增强方法就能使用注解来配置了
条件:先开启动态代理的注解方式
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
主配置文件(见上面)
目标类
package cn.dmdream.domain;
import org.springframework.stereotype.Component;
// 没有接口--为了演示cglib的动态代理
@Component("person")
public class Person
{
public void save() {
System.out.println("普通的保存方法...");
}
public void delete() {
System.out.println("普通的删除方法...");
}
public void update() {
System.out.println("普通的修改方法...");
}
public void find() {
System.out.println("普通的查询方法...");
}
}
切面类
package cn.dmdream.aspectj;
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.springframework.stereotype.Component;
// 切面类--有增强方法
@Component("myAspect")
@Aspect
public class MyAspect
{
// 增强方法
@Before(value ="execution(* cn.dmdream.domain.Person.save(..))")
public void beforeMethod()
{
System.out.println("-----beforeMethod-----");
}
// 增强方法
@AfterReturning(value="execution(* cn.dmdream.domain.Person.delete(..))")
public void aftereturningMethod()
{
System.out.println("----aftereturningMethod---");
}
// 增强方法
@Around(value="execution(* cn.dmdream.domain.Person.find(..))")
public void aroundMethod(ProceedingJoinPoint pdp) throws Throwable // 正在要执行的原有方法
{
System.out.println("之前...");
// 原有方法执行一下
pdp.proceed(); // method.invoke();
System.out.println("之后...");
}
// 增强方法
@AfterThrowing(value="execution(* cn.dmdream.domain.Person.update(..))")
public void throwingMethod()
{
System.out.println("----throwingMethod----");
}
// 增强方法
@After(value="execution(* cn.dmdream.domain.Person.update(..))")
public void afterMethod()
{
System.out.println("--不管你有没有异常,我都出来了---");
}
}
测试类
@ContextConfiguration("classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunit
{
@Autowired
private Person person;
@Test
public void test()
{
person.update();
}
}
得有一个注解类
package cn.dmdream.springconfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration // 当前类是注解类
@ComponentScan(basePackages="cn.dmdream") //
@EnableAspectJAutoProxy //
public class SpringConfig {
// 目前没有别人的类
}
目标类和切面类与上面 半xml半注解方式
相同
测试类
package cn.dmdream.demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.dmdream.domain.Person;
import cn.dmdream.springconfig.SpringConfig;
//@ContextConfiguration("classpath:applicationContext.xml") // 加载配置文件
@ContextConfiguration(classes=SpringConfig.class) //加载注解类
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunit
{
@Autowired
private Person person;
@Test
public void test()
{
person.save();
}
}
Spring的AOP
底层:动态代理
思想:将一些共性的内容进行抽取 在需要用到的地方以动态代理的形式进行插入
在不修改源码的基础上 还能对源码进行前后的增强
底层:企业开发不会自己写 因为全都封装好了
继承 httpServletRequest request; 是tomcat帮你们创建出来的
缺点: 需要知道要继承的父类是谁
装饰者模式
缺点: 需要有接口 save() 100个方法
这个接口下除了要增强的方法以外,别的方法也得实现
动态代理
jdk的动态代理 save() 100个方法
需要有接口 可以指定只增强这个接口下的哪个方法
cglib的动态代理
不需要有接口 也可以指定增强方法
缺点:代码写的多
Spring得到Junit测试不需要开启注解扫描器
spting-test.jar spring-aop.jar junit4.jar
AOP的回顾:
1 导包
AOP联盟
spring-aop.jar
aspectj.jar
spring-aspects.jar
2 编写
1 确定目标类 (里面有切入点 要被增强的方法)
2 确定切面类 (里面有通知/增强 有增强方法)
3 织入的配置 (把增强方法指定在切入点之前,之后,环绕,异常,最终执行)
jdbcTemplate是spring提供的dao层用来和数据库数据交互的技术
执行效率:A mybatis B dbutils C hibernateTemplate
dbutils:apache公司
QueryRunner qr=new QueryRunner();
qr.setDataSource(连接池);
String sql="crud";
qr.update();
qr.query();
jdbctemplate:Spring公司
jdbctemplate qr=new jdbctemplate();
qr.setDataSource(连接池);
String sql="crud";
qr.update();
qr.query();
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"
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:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">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="c3p0">property>
bean>
<bean id="accountDao" class="cn.dmdream.daoimpl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate">property>
bean>
<bean id="accountService" class="cn.dmdream.serviceImpl.AccountServiceImpl">
<property name="accountDao" ref="accountDao">property>
bean>
beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://cloud.dmdream.cn:3306/spring04?characterEncoding=UTF8
jdbc.username=root
jdbc.password=xxxx
#jdbc.driver=com.mysql.jdbc.Driver
#jdbc.url=jdbc:oracle://localhost:3306/hibernate
#jdbc.username=root
#jdbc.password=1234
#jdbc.driver=com.mysql.jdbc.Driver
#jdbc.url=jdbc:db2://localhost:3306/hibernate
#jdbc.username=root
#jdbc.password=1234
package cn.dmdream.jdbctempalte;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class Demo
{
@Test // 硬编码的方式
public void test1() throws Exception
{
// c3p0
ComboPooledDataSource ds = new ComboPooledDataSource(); //ioc
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring04");
ds.setUser("root"); // di
ds.setPassword("1234");
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(ds);
String sql="insert into account values(?,?)";
jdbcTemplate.update(sql, "jack",1000);
}
@Test // ioc+di
public void test2()
{
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate =(JdbcTemplate)context.getBean("jdbcTemplate");
String sql="insert into account values(?,?)";
jdbcTemplate.update(sql, "rose",1000);
}
}
package cn.dmdream.daoimpl;
import java.util.List;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import cn.dmdream.dao.AccountDao;
import cn.dmdream.domain.Account;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao
{
/*继承DaoSupport
*
* 1 在appliactionContext.xml文件中 使用set方式注入了 但是AccountDaoImpl没有set方法
* 2 如果自己里面没有找到 要去父类里面找 setJdbcTempalte() 找到了 注入给父类的jdbcTempalte
* 3 父类如果有了 自己子类为什么不能用jdbcTempalte 因为父类private私有化了
* 4 但是父类里面有一个getJdbcTempalte 相当于子类里面也有一个
* 5 就可以在子类中使用getJdbcTempalte的方法 获取到注入好的JdbcTempalte
* */
@Override
public void save() {
String sql = "insert into Account values(?,?)";
this.getJdbcTemplate().update(sql,"周沛3",10000);
/* String sql="insert into account values(?,?)";
getJdbcTemplate().update(sql,"Tom",100000);*/
}
@Override
public void delete() {
String sql = "delete from Account where username=?";
this.getJdbcTemplate().update(sql,"zhoupei");
}
@Override
public void update() {
String sql = "update Account set money=? where username=?";
this.getJdbcTemplate().update(sql, 1000000,"周沛");
}
@Override
public void findAll() {
String sql = "select * from Account";
List<Account> query = this.getJdbcTemplate().query(sql,new BeanPropertyRowMapper<Account>(Account.class));
for (Account account : query) {
System.out.println(account);
}
/*String sql="select * from account";
List list = getJdbcTemplate().query(sql, new BeanPropertyRowMapper(Account.class));
for (Account account : list) {
System.out.println(account);
}*/
}
@Override
public void findByname() {
String sql = "select * from Account where username = ?";
Account account = this.getJdbcTemplate().queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class),"周沛");
System.out.println(account);
/*String sql="select * from account where username=?";
Account account= jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Account.class),"jack");
System.out.println(account);*/
}
@Override
public void findCount() {
String sql = "select count(*) from Account";
Long long1 = this.getJdbcTemplate().queryForObject(sql, long.class);
System.out.println(long1);
/*String sql="select count(*) from account";
Long l = jdbcTemplate.queryForObject(sql, long.class);
System.out.println(l);*/
}
@Override
protected void checkDaoConfig() throws IllegalArgumentException {
// TODO Auto-generated method stub
}
/*
*
* set方式注入--第一种
*
* private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void save() {
String sql="insert into account values(?,?)";
jdbcTemplate.update(sql,"Tom",100000);
}
@Override
public void delete() {
String sql="delete from account where username=?";
jdbcTemplate.update(sql,"Tom");
}
@Override
public void update() {
String sql="update account set money=? where username=?";
jdbcTemplate.update(sql, 999,"rose");
}
@Override // 自己做实现
public void findAll() {
String sql="select * from account";
List list = jdbcTemplate.query(sql, new RowMapper(){
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
// 自己实现
Account account = new Account();
account.setUsername(rs.getString("username"));
account.setMoney(rs.getDouble("money"));
return account;
}});
for (Account account : list) {
System.out.println(account);
}
}
@Override
public void findAll()
{
String sql="select * from account";
List list = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Account.class));
for (Account account : list) {
System.out.println(account);
}
}
@Override
public void findByname() {
String sql="select * from account where username=?";
Account account= jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Account.class),"jack");
System.out.println(account);
}
@Override
public void findCount() {
String sql="select count(*) from account";
Long l = jdbcTemplate.queryForObject(sql, long.class);
System.out.println(l);
}*/
}
package cn.dmdream.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.dmdream.service.AccountService;
@ContextConfiguration("classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunit
{
@Autowired
private AccountService accountService;
@Test
public void test()
{
//accountService.save(); //增
//accountService.delete(); //删
//accountService.update(); // 改
//accountService.findAll(); //全查--list
//accountService.findByname();//查单个对象
accountService.findCount(); //查总个数
}
}
参考类cn.dmdream.daoimpl.AccountDaoImpl
PS:hibernateTempalte也有这2中方式
set方式注入
能使用注解
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao
{
/*
*
* set方式注入--第一种
*
* */
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void save() {
String sql="insert into account values(?,?)";
jdbcTemplate.update(sql,"Tom",100000);
}
@Override
public void delete() {
String sql="delete from account where username=?";
jdbcTemplate.update(sql,"Tom");
}
@Override
public void update() {
String sql="update account set money=? where username=?";
jdbcTemplate.update(sql, 999,"rose");
}
@Override // 自己做实现
public void findAll() {
String sql="select * from account";
List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>(){
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
// 自己实现
Account account = new Account();
account.setUsername(rs.getString("username"));
account.setMoney(rs.getDouble("money"));
return account;
}});
for (Account account : list) {
System.out.println(account);
}
}
@Override
public void findAll()
{
String sql="select * from account";
List<Account> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Account.class));
for (Account account : list) {
System.out.println(account);
}
}
@Override
public void findByname() {
String sql="select * from account where username=?";
Account account= jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Account.class),"jack");
System.out.println(account);
}
@Override
public void findCount() {
String sql="select count(*) from account";
Long l = jdbcTemplate.queryForObject(sql, long.class);
System.out.println(l);
}
}
继承的方式
不能使用注解
让jdbctemplate继承JdbcDaoSupport,说明
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao
{
/*继承DaoSupport
*
* 1 在appliactionContext.xml文件中 使用set方式注入了 但是AccountDaoImpl没有set方法
* 2 如果自己里面没有找到 要去父类里面找 setJdbcTempalte() 找到了 注入给父类的jdbcTempalte
* 3 父类如果有了 自己子类为什么不能用jdbcTempalte 因为父类private私有化了
* 4 但是父类里面有一个getJdbcTempalte 相当于子类里面也有一个
* 5 就可以在子类中使用getJdbcTempalte的方法 获取到注入好的JdbcTempalte
* */
@Override
public void save() {
String sql = "insert into Account values(?,?)";
this.getJdbcTemplate().update(sql,"周沛3",10000);
}
@Override
public void delete() {
String sql = "delete from Account where username=?";
this.getJdbcTemplate().update(sql,"zhoupei");
}
@Override
public void update() {
String sql = "update Account set money=? where username=?";
this.getJdbcTemplate().update(sql, 1000000,"周沛");
}
@Override
public void findAll() {
String sql = "select * from Account";
List<Account> query = this.getJdbcTemplate().query(sql,new BeanPropertyRowMapper<Account>(Account.class));
for (Account account : query) {
System.out.println(account);
}
}
@Override
public void findByname() {
String sql = "select * from Account where username = ?";
Account account = this.getJdbcTemplate().queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class),"周沛");
System.out.println(account);
}
@Override
public void findCount() {
String sql = "select count(*) from Account";
Long long1 = this.getJdbcTemplate().queryForObject(sql, long.class);
System.out.println(long1);
}
@Override
protected void checkDaoConfig() throws IllegalArgumentException {
}
}
//查询的得到结果集返回
list List<Account> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Account.class));
//单个对象查询
Account account= jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Account.class),"jack");
//聚合查
Long l = jdbcTemplate.queryForObject(sql, long.class);
事务有什么特性:ACID
原子性:一件完成的事情,要不全部成功 要不全部失败
转账: 加钱 减钱
一致性:事务的前后,数据总数不发生变化
jack 1000 rose 1000 2000
jack 500 rose 1500 2000
持久性:只要事务已完成(提交),数据就会到数据库中
隔离性:事务具备隔离性,如果没有隔离性,会发送读取数据的问题
不具备隔离性的话,会发生什么问题
读取数据的问题
脏读:在一个事务中,读取到了另一个事务还没有提交的数据
必须杜绝的 PS:所有的数据库都自动避免的脏读
(不可)重复读:在一个事务中,2次读取到的数据内容不一致(update)
可以允许
一个事务读到了另外一个事务提交的数据 ,造成了前后两次查询结果不一致。
虚读/幻读:在一个事务中,2次读取到的数据内容不一致(insert)
可以允许
通过调整数据库的 隔离级别 ,避免以上问题的发生
设置隔离级别
read uncommitted(读未提交) 效率最高 安全最低
引发问题: 脏读
read committed(读已提交) oracle
解决: 脏读 , 引发: 不可重复读
repeatable read(可重复读) mysql
解决: 脏读 、 不可重复读 , 未解决: 幻读
serializable(序列化) 安全最高 效率最低
解决: 脏读、 不可重复读 、 幻读。
事务的编写
获取连接
通过连接开启事务
con.setAutoCommit(false);
con.commit();
con.rollback();
如何让spring提供的事务方法在指定的save之前执行,在save之后执行?——AOP
开启事务(spring提供的方法) 增强的方法
save() 切入点
提交事务(spring提供的方法) 增强的方法
硬编码方式 可以将提供好的API以代码的方式进行事务的控制 (没人用) 纯编码方式
平台事务管理器 spring提供接口 封装事务的方法
提交方法
回滚方法
我们要用只能找这个接口的实现类来用
DataSourceTransactionManager,作用于:dbutils jdbcTempalte connnection
是切面类 里面有提交方法 回滚方法 (通知/增强)
相比于 HibernateTransactionManager,作用于: hibernate hibernateTemplate session
Hibernate版
事务的定义信息对象
如何设定/获取:
事务的隔离级别 (默认获取的就是数据库的隔离级别)
事务的超时时间 (默认 time=-1 永不超时 )
事务的是否只读 (默认 rederOnly=false 可以做任何的crud操作)
事务的传播行为:
解决的事情: 事务嵌套事务的问题
应用场景: service: a() b()
a方法有事务 b方法也有事务 在a方法中调用b方法 问:使用谁的事务?
REQUIRED(默认值): 查看当前是否有事务,如果有事务使用当前的事务,如果没事务给当前创建一个事务
a方法调用b方法:
b先看看a有没有事务,如果a没有事务,就为创建一个事务,大家一起玩
如果a有事务,就放弃自己的事务,加入到a的事务中,一起玩
让所有方法都在一个事务中
SUPPORT: 查看当前是否有事务,如果有事务就使用当前的事务,如果没事务就使用非事务
a方法调用b方法:
b先看看a有没有事务,如果a有事务,加入到a的事务中一起玩
如果a没有事务,就全部放弃事务,使用非事务执行
运行状态对象
时时查看事务的运行状态信息
查看当前事务是否完成
查看是否为新的事务
查看是否回滚
。。。
xml方式 (重点) 底层就是API的封装 直接以xml方式告诉给sping即可
需求: jack给rose转账
1.导包
2.编码
确定目标类 (TranFerServiceImpl --tranfer)
确定切面类 (用人家Spring提供的 因为spring有一个类,里面都是事务的方法)
DataSourceTransactionManager
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0">property>
bean>
增强方法:都是关于事务的
细节: 得为配了这些事务增强方法的tanfer配置一些事务参数
<tx:advice transaction-manager="transactionManager" id="txadvice">
<tx:attributes>
<tx:method name="*" read-only="false" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="tranfer"/>
tx:attributes>
tx:advice>
配置织入
专门针对事务的标签
指定那个事务用于那个切入点
<aop:config>
<aop:pointcut expression="execution(* cn.dmdream.serviceimpl.TranFerServiceImpl.tranfer(..))" id="pointcut"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>
aop:config>
完整配置文件
<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:tx="http://www.springframework.org/schema/tx"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">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="c3p0">property>
bean>
<bean id="tranFerDao" class="cn.dmdream.daoimpl.TranFerDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate">property>
bean>
<bean id="tranFerService" class="cn.dmdream.serviceimpl.TranFerServiceImpl">
<property name="tranFerDao" ref="tranFerDao">property>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0">property>
bean>
<tx:advice transaction-manager="transactionManager" id="txadvice">
<tx:attributes>
<tx:method name="tranfer" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* cn.dmdream.serviceimpl.TranFerServiceImpl.tranfer(..))" id="pointcut"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>
aop:config>
beans>
导包:
spring-tx.jar
配置在指定的方法前后用事务 (AOP)
AOP导包:
AOP联盟
spring-aop.jar
spring-aspets.jar
aspectj.jar
配置:
1 目标类:tranFerService 里面有切入点 (tranfer)
2 切面类 DataSourceTransactionManager 里面有事务的增强方法
细节1:为使用 DataSourceTransactionManager里面的事务方法配置一些事务的参数
3 配置织入
细节2: 使用事务单独的标签来配置
xml+注解(企业开发)
别人的 用xml 自己的 用注解
开启注解扫描
<context:component-scan base-package="cn.dmdream">context:component-scan>
事务的注解2步
指定开启事务的注解 告诉spirng使用的事务方法是谁的方法
<tx:annotation-driven transaction-manager="platformTransactionManager"/>
将platformTransactionManager里面的事务方法给目标类的切入点方法增强
@Transactional//(切入点)在方法上或则是类上配置
比如:给Service中的方法增强
@Service("tranFerService")
@Transactional
public class TranFerServiceImpl implements TranFerService{}
以上的两步操作代替了
事务(增强方法)配置
<tx:advice transaction-manager="platformTransactionManager" id="txadvice">
<tx:attributes>
<tx:method name="*" />
tx:attributes>
tx:advice>
配置织入过程
<aop:config>
<aop:pointcut expression="execution(* cn.dmdream.service.TransferServiceImpl.transfer(..))" id="pointcut1"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1" />
aop:config>
完整配置文件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:tx="http://www.springframework.org/schema/tx"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">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="c3p0">property>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0">property>
bean>
<context:component-scan base-package="cn.dmdream">context:component-scan>
<tx:annotation-driven transaction-manager="transactionManager"/>
beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://cloud.dmdream.cn:3306/spring04?characterEncoding=UTF8
jdbc.username=root
jdbc.password=xxxx
Dao省略
Service
package cn.dmdream.serviceimpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.dmdream.dao.TranFerDao;
import cn.dmdream.service.TranFerService;
@Service("tranFerService")
@Transactional
public class TranFerServiceImpl implements TranFerService
{
@Autowired
private TranFerDao tranFerDao;
public void tranfer(String toUser,String inUser,double money)
{
// 减钱
tranFerDao.toMoney(toUser,money);
//int i=1/0;
// 加钱
tranFerDao.inMoney(inUser,money);
}
}
测试类
package cn.dmdream.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.dmdream.service.TranFerService;
@ContextConfiguration("classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunit
{
@Autowired
private TranFerService tranFerService;
@Test
public void test()
{
tranFerService.tranfer("周沛", "周沛3", 10000);
}
}
了解即可
条件: 需要注解类
@EnableTransactionManagement
代替了
在方法的形参使用注解@Qualifier(“c3p0”)
public JdbcTemplate createJdbcTemplate(@Qualifier(“c3p0”) DataSource ds) // 使用注解注入对象
其它设置和半xml方式一样
SpringConfig.java
package cn.dmdream.springconfig;
import java.beans.PropertyVetoException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration
@ComponentScan(basePackages="cn.dmdream")
@EnableTransactionManagement //
public class SpringConfig
{
// 创建出来c3p0 给spring
@Bean(name="c3p0")
public DataSource createDataSourceC3p0() throws PropertyVetoException
{
ComboPooledDataSource ds = new ComboPooledDataSource(); //ioc
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/spring04");
ds.setUser("root"); // di
ds.setPassword("1234");
return ds;
}
@Bean(name="jdbcTemplate")
public JdbcTemplate createJdbcTemplate(@Qualifier("c3p0") DataSource ds) // 使用注解问spring要
{
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(ds);
return jdbcTemplate;
}
@Bean(name="transactionManager")
public DataSourceTransactionManager createDataSourceTransactionManager(@Qualifier("c3p0") DataSource ds) // 使用注解问spring要
{
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(ds);
return dataSourceTransactionManager;
}
}