spring随笔(三)DataBase

1,Data access with JDBC

使用springJdbc非常简单。在我们写daoImpl的时候只需要继承spring的org.springframework.jdbc.core.support.JdbcDaoSupport该类。在实现以下需要实现的接口即可,再在需要实现的接口方法中使用通过继承JdbcDaoSupport类的jdbcTemplate对象的update、execute、query等方法完成我们需要的方法即可。

比如我们要写一个UserDaoImpl类泽代码如下:

package com.xiaohui.jdbc;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class UserDaoImpl extends JdbcDaoSupport implements IUserDao {
	@Override
	public void save(User u) {
		String sql = "INSERT INTO user VALUES(NULL,?)";
		this.getJdbcTemplate().update(sql, u.getName());
	}

	@Override
	public void update(User u) {
		String sql = "UPDATE  user SET name =? WHERE id=?";
		this.getJdbcTemplate().update(sql, u.getName(), u.getId());
	}

	@Override
	public void delete(Long id) {
		this.getJdbcTemplate().execute("delete from user where id=" + id);
	}

	@Override
	public List<User> list() {
		String sql = "SELECT * FROM user";
		List<User> users = this.getJdbcTemplate().query(sql,
				new ResultSetExtractor<List<User>>() {
					@Override
					public List<User> extractData(ResultSet rs)
							throws SQLException, DataAccessException {
						List<User> userList = new ArrayList<User>();
						while (rs.next()) {
							User user = new User();
							user.setId(rs.getLong("id"));
							user.setName(rs.getString("name"));
							userList.add(user);
						}
						return userList;
					}
				});
		return users;
	}

	@Override
	public User getById(final Long id) {
		String sql = "select * from user where id=?";
		User u = this.getJdbcTemplate().execute(sql,
				new PreparedStatementCallback<User>() {
					@Override
					public User doInPreparedStatement(PreparedStatement ps)
							throws SQLException, DataAccessException {
						ps.setLong(1, id);
						ResultSet set = ps.executeQuery();
						while (set.next()) {
							User u = new User();
							u.setId(id);
							u.setName(set.getString("name"));
							return u;
						}
						return null;
					}
				});
		return u;
	}
}


同时我们需要给属性jdbcTemplate在xml中配置属性值xml如下:需要在source folder目录下创建一个jdbc.properties。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	 	xmlns:context="http://www.springframework.org/schema/context"
       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-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
    <context:property-placeholder location="classpath:jdbc.properties"/>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate" scope="prototype">
    	<property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="userdao" class="com.xiaohui.jdbc.UserDaoImpl">
    	<property name="jdbcTemplate" ref="template"/>
    </bean>
</beans>


这样我们就可以通过获取userdao 来与数据库交互了。

2,spring事务管理

事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差错,比如有一条SQL语句没有执行成功,那么这一组操作都将全部回滚。

事务特性:

  • atomic(原子性):要么都发生,要么都不发生。
  • consistent(一致性):数据应该不被破坏。
  • solate(隔离性):用户间操作不相混淆。
  • Durable(持久性):永久保存,例如保存到数据库中等。

spring提供的两种事务管理方式 基于xml的事务管理和基于aop注解的管理事务。在spring中spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现

事务管理器实现
目标
org.springframework.jdbc.datasource.DataSourceTransactionManager
在单一的JDBC Datasource中的管理事务
org.springframework.orm.hibernate3.HibernateTransactionManager
当持久化机制是hibernate时,用它来管理事务
org.springframework.jdo.JdoTransactionManager
当持久化机制是Jdo时,用它来管理事务。
org.springframework.transaction.jta.JtaTransactionManager
使用一个JTA实现来管理事务。在一个事务跨越多个资源时必须使用
org.springframework.orm.ojb.PersistenceBrokerTransactionManager
当apache的ojb用作持久化机制时,用它来管理事务。

 

理解事务属性--事物传播规则
  • REQUIRED    :业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务
  • NOT_SUPPORTED :声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行
  • REQUIRESNEW属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原先的事务才会恢复执行
  • MANDATORY:该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果业务方法在没有事务的环境下调用,容器就会抛出例外
  • SUPPORTS这一事务属性表明,如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行
  • Never:指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能正常执行
  • NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效

1,基于注解的方式管理事务。

基于注解的使用比较简单,只要在xml中引入tx命名空间,并配置事务管理器transactionManager  xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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-3.0.xsd
           http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
	
	<!-- springJdbc -->
	<context:property-placeholder location="jdbc.properties" />
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close" >
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager" />
	<bean id="accDao" class="com.xiaohui.trans.AccountDaoImpl">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<bean id="accountService" class="com.xiaohui.trans.AccountServiceImpl">
		<property name="dao" ref="accDao"></property>
	</bean>
</beans>

 这时在业务层需要开启事务的方法上面加上@Transactional注解即可。

@Transactional
public void trans(Account accIn, Account accOut, Double amount) {
	// 转出金额
	dao.transOut(accOut, amount);
	// 转入金额
	dao.transIn(accIn, amount);
}


如上则在转账的过程里出现任何异常事物会回滚,都不会影响到数据库底层数据的。

2,基于xml配置的事务管理

使用xml配置管理事务,我们同样需要告诉spring容器,我们使用具体的什么管理器,jdbc的还是hibernate的,所以还需要配置transactionManager,这次我们需要使用aop来管理我们的事物。

这次我们需要加入aop的命名空间,再将上面的

<tx:annotation-driven transaction-manager="transactionManager" />

xml代码替换为:

<aop:config>
 <aop:pointcut expression="execution(* com.xiaohui.trans.*ServiceImpl.*(..))" id="pointcut"/>
 <aop:advisor advice-ref="transAdvice" pointcut-ref="pointcut"/>
 </aop:config>
 <tx:advice id="transAdvice">
 	<tx:attributes>
 		<tx:method name="trans"/>
 		<tx:method name="transIn" propagation="REQUIRED"/>
 		<tx:method name="transOut" propagation="REQUIRED"/>
 	</tx:attributes>
 </tx:advice>

即可。

spring随笔(三)DataBase,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。