Spring 框架 四天学习笔记_day03

本文详细介绍了Spring AOP的应用、Spring整合JDBC的方法及示例代码,并讲解了如何利用Spring进行事务管理。

1.复习

        1. spring . aop开发  

                    aop思想, 纵向重复, 横向抽取

                             |-filter 中

                             |-动态代理    

                             |-interceptor 中  struts2框架中的拦截器

                     spring AOP : 封装了动态代理技术, 来体现aop

                      springaop实现: 可以对所有的对象代理

                             |-动态代理, 代理实现接口 

                             |-cglib代理,对目标对象继承代理

                     springaop名词: 

                                            join point : 连接点, 所有可以植入通知的方法

                                            point cut : 切入点,需要已经织入的通知的方法

                                            advice : 需要增强的代码

                                            weaving: 动词, 将通过应用的切点的过程

                                            target : 目标对象 

                                            proxy : 代理对象 

                                            aspect : 切面,切入点,+ 通知

           2.spring 中的springaop 的应用

                1.导包
4+2
2 aop+aspect
2 aop联盟+weaving
2.准备目标对象


3.准备通知类
前置通知
后置通知 方法正常结束
环绕通知
异常拦截通知
后置通知 无论如何都执行

4.配置文件中配置,导入aop约束
1>目标对象
2>通知对象
3><aop:config>
<aop:ponint-cut id="切点名称" expression="execution(切点表达式)" />
<aop:aspect ref="通知对象名称" >
<aop:before method="" ponintcut-ref=""  />
<aop:after-returning method="" ponintcut-ref=""  />
<aop:around method="" ponintcut-ref=""  />
<aop:after-throwing method="" ponintcut-ref=""  />
<aop:after method="" ponintcut-ref=""  />
</aop:aspect>

扩展:使用注解完成aop
1.导包
4+2
2 aop+aspect
2 aop联盟+weaving
2.准备目标对象


3.准备通知类
4.配置文件中配置,导入aop约束
1>目标对象
2>通知对象
3><aop:aspect-autoproxy> 开启注解aop

5.注解
@Aspect 指定当前类是通知类

@Before 前置通知方法
@after-returning 后置通知方法
@around 环绕通知方法
@after-throwing 异常拦截通知方法
@after 后通知方法

@PointCut 抽取切点表达式

2.spring整合jdbc  (spring 中封装了jdbc对象, 通过这个对象可以操作数据库,这个对象叫做,JDBCTemplate, 和dbutils 中的queryrunner 几乎一模一样)


       2.1 整合jdbc 模板

    1. 导包


        2.使用核心类,操作数据库

    

	@Test
	public void test() throws Exception {
		// 0. 准备连接池
		ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
		dataSource.setJdbcUrl("jdbc:mysql:///hibernate");
		dataSource.setDriverClass("com.mysql.jdbc.Driver");
		dataSource.setUser("root");
		dataSource.setPassword("123456");
		
		
		// 1.创建jdbc 模板对象 
		JdbcTemplate jt = new JdbcTemplate(dataSource); 
		
		// 书写sql 
		String sql = "insert into s_user values(3,'rose','4545')" ; 
		jt.update(sql); 
	}
2.2  演示

        1.定义dao 接口

package com.zzq.dao;

import java.util.List;

import com.zzq.domain.User;

/**
 *  dao 定义对user 的操作
 * @author ZZQ.Hacker
 *
 */
public interface UserDao {

	 void add (User user); 
	 void delete(Integer id ) ; 
	 void update(User user);
	  List<User> findAll(); 
	  User getById(Integer id ) ;
	 Integer getTotalCount();
	 
}

2.定义dao 实现类

package com.zzq.dao.impl;


import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.zzq.dao.UserDao;
import com.zzq.domain.User;

@SuppressWarnings("all")
public class UserDaoimpl  implements UserDao {
	private static JdbcTemplate jt ; 
	static{
		try{
		// 0. 准备连接池
				ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
				dataSource.setJdbcUrl("jdbc:mysql:///hibernate");
				dataSource.setDriverClass("com.mysql.jdbc.Driver");
				dataSource.setUser("root");
				dataSource.setPassword("123456");
				
				
				// 1.创建jdbc 模板对象 
			 jt = new JdbcTemplate(dataSource); 
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	public void add(User user) {
		String sql = "insert into s_user values(?,?,?); " ; 
		jt.update(sql, user.getId(),user.getName(),user.getPassword()); 
	}


	public void delete(Integer id) {
		String sql = "delete from s_user where id = ?  " ;
		jt.update(sql,id); 
	}

	public void update(User user) {
		String sql = "update s_user set name=? password=? where id=?  " ; 
		jt.update(sql,user.getName(),user.getPassword(),user.getId()); 
	}


	public List<User> findAll() {
		String sql =  "select * from s_user" ; 
		List<User>  users= jt.query(sql, new RowMapper<User>(){

			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User user = new User()  ; 
				user.setId(rs.getInt("id"));
				user.setName(rs.getString("username"));
				user.setPassword(rs.getString("password"));
				return user;
			}
			
		}); 
		return  users;
	}
	
	
	

	public User getById(Integer id) {
		String sql = "select * from s_user where id = ? ";
		User user = jt.queryForObject(sql,new RowMapper<User>(){

			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				// 把resultset 中的内容取出,然后进行 封装,  int 是索引 
				User  u = new User() ;
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("name"));
				u.setPassword(rs.getString("password"));
				return u  ;
			}
			
		}, id );  
		
		return   null  ; 
	}


	public Integer getTotalCount() {
			String sql =  "select count(*) from s_user"; 
			return jt.queryForObject(sql, Integer.class); 
			
	}
 
	
}

4.测试

package com.zzq.jdbctempate;

import java.util.List;



import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;


import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.zzq.dao.UserDao;
import com.zzq.dao.impl.UserDaoimpl;
import com.zzq.domain.User;

/**
 * 演示jdbc 模板
 * @author ZZQ.Hacker
 *
 */
public class Demo {

	private UserDao u  =new UserDaoimpl(); 
	
	
	@Test
	public void test() throws Exception {
		// 0. 准备连接池
		ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
		dataSource.setJdbcUrl("jdbc:mysql:///hibernate");
		dataSource.setDriverClass("com.mysql.jdbc.Driver");
		dataSource.setUser("root");
		dataSource.setPassword("123456");
		
		
		// 1.创建jdbc 模板对象 
		JdbcTemplate jt = new JdbcTemplate(dataSource); 
		
		// 书写sql 
		String sql = "select *  from s_user" ;
		List query = jt.query(sql,new BeanPropertyRowMapper(User.class)); 
		System.out.println(query);
	}
	
	
	
	@Test
	public  void test_findAll(){
		List<User> list = u.findAll(); 
		System.out.println(list);
		
	}
	
}

3.jdbc连接池,dao 配置到spring容器中

        bug : 注意, 这里要理解, spring其实就是一个容器, 通过配置文件可以放入中, 配置文件可以是set 放入 , 和构造方法放入, 然后我们通过注解 @reSource  进行取出, 所以放进去的需要的时候就可以进行取出, 我今天就在这里犯了个错误 ,存入了jdbcTemplate 但是没有取出 ,然后我就直接想进行获取dao 然后进行查询 代码如下 

    1. daoimpl 层代码

package com.zzq.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.zzq.dao.UserDao;
import com.zzq.domain.User;

public class UserDaoimpl extends JdbcDaoSupport implements UserDao {
	@Resource(name="jdbcTemplate")
	private JdbcTemplate jt; 

	public Integer getTotalCount() {
		String sql = "select count(*) from s_user  ";
		Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);
		return count;
	}

	public List<User> findAll() {
		String sql = "select * from s_user  ";
		List<User> list = jt.query(sql, new RowMapper<User>(){
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("username"));
				u.setPassword(rs.getString("password"));
				return u;
			}});
		return list;
	}


}  // 这里注意, 一定要从spring 中取出 ,对象 ,然后才能进行操作 

配置文件如下: 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

	<bean name="user" class="com.zzq.domain.User"></bean>
	
	

	<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
				<property name="jdbcUrl" value="jdbc:mysql:///hibernate"></property>
				<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
				<property name="user" value="root" ></property>
				<property name="password" value="123456"></property>
	</bean>
	
	
	<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
 	<bean name="userDao" class="com.zzq.dao.impl.UserDaoimpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean> 
	

</beans>

测试如下 : 

package com.zzq.jdbctempate;



import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.zzq.dao.UserDao;
import com.zzq.dao.impl.UserDaoimpl;
import com.zzq.domain.User;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {

	@Resource(name="userDao")
	private UserDao us ;  
	
	@Test
	public void test(){
		System.out.println(us.findAll());
	}
	
	
	@Test
	public void test2(){
		System.out.println(us.getTotalCount());
	}
}
2.3 Spring 整合jdbc 扩展, jdbcdaosupport  

    如果daoimpl 继承了    jdbcdaosupport  , jdbcdaosupport 会自动读取配置文件中的

JdbcTemplate

对象, 然后我们直接调用父类的方法即可, 效果如下用super 关键字 调用父类的方法  : 


本来我们需要把 ,dataSource 数据源放入,jdbcTempate 中, 然后把jdbctempate 注入到dao 中, 但是用了这个之后 , 关系变了, 直接把dataSource  传入jdbcTempate 然后通过继承关系, 直接就dao 用了jdbctemapte 模板对象 , 所以使得关系变得简单


2.4  读取properties 配置文件 

  由于, 由于程序的可拓展性, 所以用一个properties书写数据库的链接  , 在Spring 中 properties 书写时候 ,最好加一个前缀, 因为, 有的建容易和其他的冲突, 前缀随便加, 效果如下 : 

 

jdbc.jdbcUrl=jdbc:mysql:///hibernate
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=123456

然后我们在applicationContext 引入properties 文件, 用context 标签, 需要引入context 约束的哦,然后用local host 属性, 填写地址  ,然后即可


3. springAop 事务管理

    3.1 复习 

            1.事务特性, :acid  

                       原子性 : 强调事务的不可分割

                        一致性: 事务执行前后数据的完整性一直 

                       隔离性 : 一个事务的执行不受任何干扰

                        持久性: 事务一旦执行, 就永久保存进数据库 

            2. 并发问题

                    脏读,一个是事务读到了一个未提交的事务

                    不可重复读,   一个事务都到了一个已经提交的事务, 导致事务进行了两次

                      幻读, 一个事务读到了一个已经提交的insert 事务, 导致,多次查询不一致 

            3. 事务的隔离级别 

                    未提交读 : 脏读, 不可重复度,虚读有可能发生

                    已提交读: 避免脏读, 但是不可重复读,和虚读都有可能发生

                    可重复读 :  避免脏读和不可重复读 ,但是虚读都有可能发生 

                     串行化 : 避免以上所有的问题 

mysql : 默认是可重复读 

oracle  : 默认是已提交

    3.2  spring  封装了管理代码 (开启事务的代码, 提交事务的代码,回滚事务的代码)

     因为不同的平台,操作的事务代码各不相同, spring 提供了一个接口 

    1.PlatformTransactionManager  接口  

    JDBCTransactionManager     jdbc  平台 实现类

    HibernateTransactionManager   hibernate 平台 实现类

注意 : 在spring 中玩事务, 最核心的对象就是TransactionManager   

       2.spring 中的管理事务的属性介绍

            事务的隔离级别

            事务是否只读(如果为只读, 就不能操作数据库中的数据)

            事务的传播行为 



3.3 事务演示

    银行转账案例 :

         我们通过事务控制,然后让两个用户之间相互转账

注意 : bug   我们注入的时候 , 一定要name对着相应的配置文件才可以 

    3.2.1 使用代码进行管理事务 (这种方式很少用的 )
dao 层:

package com.zzq.dao.impl;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.zzq.dao.AccountDao;

public class AccountDaoimpl extends JdbcDaoSupport implements AccountDao {

	// 加钱
	public void increaseMoney(Integer id, Double money) {
		String sql = "update t_account set money =money+? where id=? " ; 
		this.getJdbcTemplate().update(sql, money,id); 
		
	}
            //减钱
	public void decreaseMoney(Integer id, Double money) {
		String sql = "update t_account set money =money-? where id=? " ; 
		super.getJdbcTemplate().update(sql,money,id); 
	}

	
}

  书写service 层 : 

        

package com.zzq.service.impl;


import org.springframework.transaction.TransactionStatus;

import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.zzq.dao.AccountDao;
import com.zzq.service.AccountService;

public class AccountServiceimpl implements AccountService{
   // 让dao层注入进来


	private AccountDao acc ;
	private TransactionTemplate  transactionTemplate   ;
	




	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}





	public void setAcc(AccountDao acc) {
		this.acc = acc;
	}



	public void transfer(final Integer from, final Integer to, final Double money) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
	
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				
				
				// 减少钱
				acc.decreaseMoney(from,money);
				// 加钱
				acc.increaseMoney(to, money);
				
			}
			
		}); 
		
	}



		
	
	
}

配置文件配置 :


首先我们创建transactionmanger 事务控制核心类 事务核心类需要依赖datasource 的链接对象, 

然后创建事务模板对象

3.3.2 使用配置文件管理事务(aop)  spring为我们准备了事务通知(环绕通知)

1. 首先我们要配置通知  我们可以通过*进行匹配性的代理 事务

    

2.植入通知与切点结合 形成切面


    这里的execution 表达式, 中的*表示统配

注意 : 一定要注入事务和dao层, 不然抛异常 提供和set 方法 进行注入


3.3.3 注解进行控制事务

通过注解

配置文件中开启注解控制事务的代码 配置这个之后  就可以用注解配置事务


@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)

这个注解直接放在方法的头上即可, 但是这样每个方法都要加这个注解, 显得臃肿, 因此我们可以直接写在类上


如果下面的方法有不同, 就在每个单独的方法进行加这个注解


今天的课程笔记完结 !!! 明天激动人心的 spring 整合 struts2  hibernate  哈哈 然后Oracle 







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值