Spring的事务管理:

  事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层,即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。  
  在 Spring 中通常可以通过以下三种方式来实现对事务的管理:
    (1)使用 Spring 的事务代理工厂管理事务
    (2)使用 Spring 的事务注解管理事务
    (3)使用 AspectJ 的 AOP 配置管理事务

  Spring事务管理API:

    Spring 的事务管理,主要用到两个事务相关的接口。

    (1)事务管理器接口
        事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事务的状态信息。查看 SpringAPI 帮助文档:Spring 框架解压目录下的docs/javadoc-api/index.html。

Modifier and Type Method and Description
void commit(TransactionStatus status)

Commit the given transaction, with regard to its status.
TransactionStatus getTransaction(TransactionDefinition definition)

Return a currently active transaction or create a new one, according to the specified propagation behavior.
void rollback(TransactionStatus status)

Perform a rollback of the given transaction.

      A、常用的两个实现类
        PlatformTransactionManager 接口有两个常用的实现类:  
          DataSourceTransactionManager:使用 JDBC 或 iBatis  进行持久化数据时使用。  
          HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。
      B、Spring 的回滚方式
        Spring 事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交。不过,对于受查异常,程序员也可以手工设置其回滚方式。

    (2)事务定义接口:
      事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:事务隔离级别、事务传播行为、事务默认超时时限,及对它们的操作。

      A、定义了五个事务隔离级别常量:
        这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。
          DEFAULT:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ;  Oracle默认为 READ_COMMITTED。
          READ_UNCOMMITTED:读未提交。未解决任何并发问题。
          READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。  
          REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读  
          SERIALIZABLE:串行化。不存在并发问题。

      B、定义了七个事务传播行为常量
        所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的维护情况,就称为事务传播行为。事务传播行为是加在方法上的。  
事务传播行为常量都是以 PROPAGATION_  开头,形如 PROPAGATION_XXX。  
          REQUIRED:指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是Spring 默认的事务传播行为。  
          如该传播行为加在 doOther()方法上。若 doSome()方法在执行时就是在事务内的,则 doOther()方法的执行也加入到该事务内执行。若 doSome()方法没有在事务内执行,则 doOther()方法会创建一个事务,并在其中执行。

          SUPPORTS:指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。

          MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常。

          REQUIRES_NEW:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

          NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起。

          NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常。

          NESTED:指定的方法必须在事务内执行。若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务。

      C、定义了默认事务超时时限
        常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,及不支持事务超时时限设置的 none 值。
        注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般就使用默认值即可。

  Spring事务代码详解:

    要求:实现模拟购买股票。存在两个实体:银行账户 Account 与股票账户 Stock。当要购买股票时,需要从 Account 中扣除相应金额的存款,然后在 Stock 中增加相应的股票数量。而在这个过程中,可能会抛出一个用户自定义的异常。异常的抛出,将会使两个操作回滚。

    Step1:创建数据库表 account、stock
    Step2:创建实体类 Account 与 Stock (略)
    Step3:定义 Dao 接口  IAccountDao 与 IStockDao

 package com.tongji.dao;

 public interface IAccountDao {

     void insertAccount(String aname, double money);

     void updateAccount(String aname, double money, boolean isBuy);

 }
 package com.tongji.dao;

 public interface IStockDao {

     void insertStock(String sname, int amount);

     void updateStock(String sname, int amount, boolean isBuy);

 }

    Step4:定义 Dao 实现类 AccountDaoImpl 与 StockDaoImpl

 package com.tongji.dao;

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

 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

     @Override
public void insertAccount(String aname, double money) {
String sql = "insert into account(aname, balance) values(?,?)";
this.getJdbcTemplate().update(sql, aname, money);
} @Override
public void updateAccount(String aname, double money, boolean isBuy) {
String sql = "update account set balance=balance+? where aname=?";
if (isBuy) {
sql = "update account set balance=balance-? where aname=?";
}
this.getJdbcTemplate().update(sql, money, aname); } }
 package com.tongji.dao;

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

 public class StockDaoImpl extends JdbcDaoSupport implements IStockDao {

     @Override
public void insertStock(String sname, int amount) {
String sql = "insert into stock(sname, count) values (?,?)";
this.getJdbcTemplate().update(sql , sname, amount);
} @Override
public void updateStock(String sname, int amount, boolean isBuy) {
//isBuy为true,则表示购买股票,此时应增加股票账户中的股票数量
String sql = "update stock set count=count-? where sname=?";
if (isBuy) {
sql = "update stock set count=count+? where sname=?";
}
this.getJdbcTemplate().update(sql, amount, sname);
} }

    Step5:定义异常类 StockException

 package com.tongji.beans;

 public class StockException extends Exception {
private static final long serialVersionUID = 5377570098437361228L; public StockException() {
super();
} public StockException(String message) {
super(message);
} }

    Step6:定义 Service 接口 IStockProcessService

 package com.tongji.service;

 public interface IStockProcessService {
void openAccount(String aname, double money);
void openStock(String sname, int amount);
void buyStock(String aname, double money, String sname, int amount);
}

    Step7:定义 service 的实现类 StockProcessServiceImpl

 package com.tongji.service;

 import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.tongji.beans.StockException;
import com.tongji.dao.IAccountDao;
import com.tongji.dao.IStockDao; public class StockProcessServiceImpl implements IStockProcessService{
private IAccountDao accountDao;
private IStockDao stockDao; public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
} public void setStockDao(IStockDao stockDao) {
this.stockDao = stockDao;
} @Override
public void openAccount(String aname, double money) {
accountDao.insertAccount(aname, money);
} @Override
public void openStock(String sname, int amount) {
stockDao.insertStock(sname, amount);
} @Override
public void buyStock(String aname, double money, String sname, int amount) throws StockException {
boolean isBuy = true;
accountDao.updateAccount(aname, money, isBuy);
//故意抛出异常
if (true) {
throw new StockException("购买股票异常");
}
stockDao.updateStock(sname, amount, isBuy);
} }

    Step8:定义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: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"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean>
</beans>

    Step9:测试类

 package com.tongji.test;

 import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tongji.service.IStockProcessService; public class MyTest { private IStockProcessService service; @Before
public void before() {
//创建容器
@SuppressWarnings("resource")
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
service = (IStockProcessService) ac.getBean("stockService");
} @Test
public void testOpen() {
service.openAccount("张三", 10000);
service.openStock("华为", 5);
} @Test
public void testBuyStock() {
service.buyStock("张三", 2000, "华为", 5);
} }

    此配置文件没有采用事务管理,所以购买股票的时候,出现了数据库中账户金额减少了,但是股票数目没有增加的不一致情况。

  

  使用 Spring 的事务代理工厂管理事务:

    该方式是,需要为目标类,即 Service 的实现类创建事务代理。事务代理使用的类是TransactionProxyFactoryBean,该类需要初始化如下一些属性:
      (1)transactionManager:事务管理器
      (2)target:目标对象,即 Service 实现类对象
      (3)transactionAttributes:事务属性设置
      对于 XML 配置代理方式实现事务管理时,受查异常的回滚方式,程序员可以通过以下方式进行设置:通过“-异常”方式,可使发生指定的异常时事务回滚;通过“+异常”方式,可使发生指定的异常时事务提交。

    修改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: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"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 生成事务代理 -->
<bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTxManager"/>
<property name="target" ref="stockService"/>
<property name="transactionAttributes">
<props>
<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop>
</props>
</property>
</bean>
</beans>

    由于本项目使用的是 JDBC 进行持久化,所以使用 DataSourceTransactionManager 类作为事务管理器。

    修改测试类:

     public void before() {
           //创建容器
           @SuppressWarnings("resource")
           ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
           service = (IStockProcessService) ac.getBean("stockServiceProxy");
       }

  使用 Spring 的事务注解管理事务:
    通过@Transactional 注解方式,也可将事务织入到相应方法中。而使用注解方式,只需在配置文件中加入一个 tx 标签,以告诉 spring 使用注解来完成事务的织入。该标签只需指定一个属性,事务管理器。

    修改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: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/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"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 开启注解驱动 -->
<tx:annotation-driven transaction-manager="myTxManager"/>
</beans>

    修改 service 的实现类 StockProcessServiceImpl:

 package com.tongji.service;

 import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.tongji.beans.StockException;
import com.tongji.dao.IAccountDao;
import com.tongji.dao.IStockDao; public class StockProcessServiceImpl implements IStockProcessService{
private IAccountDao accountDao;
private IStockDao stockDao; public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
} public void setStockDao(IStockDao stockDao) {
this.stockDao = stockDao;
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
public void openAccount(String aname, double money) {
accountDao.insertAccount(aname, money);
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
public void openStock(String sname, int amount) {
stockDao.insertStock(sname, amount);
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED, rollbackFor=StockException.class)
public void buyStock(String aname, double money, String sname, int amount) throws StockException {
boolean isBuy = true;
accountDao.updateAccount(aname, money, isBuy);
if (true) {
throw new StockException("购买股票异常");
}
stockDao.updateStock(sname, amount, isBuy);
} }

    @Transactional 的所有可选属性如下所示:
      propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为Propagation.REQUIRED。
      isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为Isolation.DEFAULT。
      readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值为 false。
      timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为-1,即没有时限。
      rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
      rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
      noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
      noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
     需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。  
    若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

  使用 AspectJ 的 AOP 配置管理事务(重点):

    使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类较多,配置文件会变得非常臃肿。使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。

    修改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: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/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"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册事务通知 -->
<tx:advice id="txAdvice" transaction-manager="myTxManager">
<tx:attributes>
<!-- 指定在连接点方法上应用的事务属性 -->
<tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
</tx:attributes>
</tx:advice> <!-- AOP配置 -->
<aop:config>
<!-- 指定切入点 -->
<aop:pointcut expression="execution(* *..service.*.*(..))" id="stockPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="stockPointCut"/>
</aop:config>
</beans>

  总结:Spring 的事务管理,是 AOP 的应用,将事务作为切面织入到了 Service 层的业务方法中。

Spring4笔记9--Spring的事务管理(AOP应用的例子)的更多相关文章

  1. Spring初学之spring的事务管理注解

    spring的事务管理,本文的例子是:比如你需要网购一本书,卖书的那一方有库存量以及书的价格,你有账户余额.回想我们在编程中要实现买书这样的功能,由于你的账户表和书的库存量表肯定不是同一张数据库表,所 ...

  2. Spring学习笔记五:Spring进行事务管理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html  事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...

  3. Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明

    Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config>  <aop:pointcut expression= ...

  4. 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例

    Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...

  5. Hibernate与Spring的事务管理

    什么是事务 这个问题比较大,按照我的理解就是,一个事务内的n个操作,要么全部完成,一旦有一个操作有问题,那么所有的操作都全部回滚. Jdbc的事务 首先,大家已经知道了,事务说白了就是一个词----统 ...

  6. Spring的事务管理

    事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...

  7. Spring应用——事务管理

    事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...

  8. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  9. Spring高级事务管理难点剖析

    1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...

  10. CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

    JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...

随机推荐

  1. Linux/Unix系统编程手册 第三章:系统编程概念

    本章介绍系统编程的基础概念和一些后续章节用到的函数及头文件,并说明了可移植性问题. 系统调用是受控的内核入口,通过系统调用,进程可以请求内核以自己的名义去执行某些动作,比如创建子进程,执行I/O操作, ...

  2. C# QR二维码DEMO

    QR二维码 二维码的一种 相关类库 ThoughtWorks.QRCode 第三方类库 DEMO功能 Encode 生成二维码图片 Encoding 编码 Correction Level 等级 Ve ...

  3. iOS 一些常见问题

    1.屏幕横屏时 xib上拖拉的控件不会跟着横过来: 是因为在主文件面里的 main interface 方框里的main 没有删除: 2.运行出现你没有权限 : 清理一下: 3.将对象转成字符串: / ...

  4. 更新ffmpeg

    今天对公司线上的几台机器做了下ffmpeg的更新,没有什么技术含量,还是简单记录下,做个流水账~哈哈 软件包获取方式 官方网站:https://ffmpeg.org/download.htmlgith ...

  5. JDBC数据库连接技术

    [学习笔记]JDBC数据库连接技术(Java Database Connectivity) 一.JDBC简介 Java是通过JDBC技术实现对各种数据库的访问的,JDBC是Java数据库连接技术的简称 ...

  6. Qt——线程与定时器

    一.定时器QTimer类 The QTimer class provides repetitive and single-shot timers. The QTimer class provides ...

  7. 01 Spring Boot 的简单配置和使用

    Spring Boot 简介 使用 Spring Boot 可以让我们快速创建一个基于 Spring 的项目,而让这个 Spring 项目跑起来我们只需要很少的配置就可以了. 创建 Spring Bo ...

  8. 51nod 1681 公共祖先 | 树状数组

    51nod 1681 公共祖先 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完 ...

  9. Java考试题之五

    QUESTION 102 Given: 23. Object [] myObjects = { 24. new Integer(12), 25. new String("foo") ...

  10. 解题:CF983B pyramid

    题面 题目都告诉我们是“金字塔”了,不妨分析分析$f$的性质 $f(a_1,a_2)=f(a_1$ $xor$ $a_2)=a1$ $xor$ $a_2$ $f(a_1,a_2,a_3)=f(a_1$ ...