Spring4 事务管理

本章是Spring4 教程中的最后一章,也是非常重要的一章。如果说学习IOC是知识的入门,那学习事务管理就是知识的提升。本章篇幅可能有一丢丢长,也有一丢丢难,需要读者细细品味。主要从三个方面开始:事务简介,基于注解的事务管理 和基于xml的事务管理。


准备环境

mysql文件,两张表:一个用户表,字段有帐号和余额。一个商品表,字段有sku,售价和库存。

  1. DROP TABLE IF EXISTS `user`;
  2. CREATE TABLE `user` (
  3. `id` bigint(20) NOT NULL,
  4. `account` varchar(255) NOT NULL,
  5. `balance` float DEFAULT NULL COMMENT '用户余额',
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  8. -- ----------------------------
  9. -- Records of user
  10. -- ----------------------------
  11. INSERT INTO user VALUES ('1', 'itdragon', '100');
  1. DROP TABLE IF EXISTS `product`;
  2. CREATE TABLE `product` (
  3. `id` bigint(20) NOT NULL,
  4. `sku` varchar(255) NOT NULL COMMENT '商品的唯一标识',
  5. `price` float NOT NULL COMMENT '商品价格',
  6. `stock` int(11) NOT NULL COMMENT '商品库存',
  7. PRIMARY KEY (`id`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  9. -- ----------------------------
  10. -- Records of product
  11. -- ----------------------------
  12. INSERT INTO product VALUES ('1', 'java', '40', '10');
  13. INSERT INTO product VALUES ('2', 'spring', '50', '10');

事务简介

工作中应该经常听到:"这是一个事务,你要保证它数据的一致性,在这里加个注解吧!"。于是我们就稀里糊涂地用,好像也没出什么问题。

因为加上注解,说明该方法支持事务的处理。事务就是一系列的动作,这一系列的动作要么都成功,要么都失败。所以你才会觉得没出什么问题。管理事务是应用程序开发必不可少的技术,用来确保数据的完整性和一致性,特别是和钱有关系的事务。

事务有四个关键属性:

** 原子性 **:一系列的动作,要么都成功,要么都失败。

** 一致性 **:数据和事务状态要保持一致。

** 隔离性 **:为了防止数据被破坏,每个事务之间都存在隔离性。

** 持久性 **:一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响。

我们用例子更好地说明事务:

A给B转账,A出账500元,B因为某种原因没有成功进账。若A出账的500元不回滚到A账户余额中,就会出现数据的不完整性和不一致性的问题。

本章模拟用户购买商品的场景。商场的下单逻辑是:先发货后设置用户余额。如果用户余额充足,商品库存充足的情况,是没有什么问题的。但若余额不足却购买商品,库存减少了,扣除用户余额时会因为余额不足而抛出异常,到最后用户余额并没有减少,商品库存却减少了,显然是不合理的。现在我们用Spring的事务管理来解决这种问题。


基于注解的事务管理

核心文件 applicationContext.xml。既然用到注解,就需要配置自动扫描包context:component-scan,还需要配置JdbcTempalte。最后要配置事务管理器和启动事务注解 tx:annotation-driven

JDBC配置的事务管理器的class指定路径是DataSourceTransactionManager,

Hibernate配置的事务管理器的class指定路径是HibernateTransactionMannger 。两个的用法都是一样,只是配置事务管理时class指定的路径不同罢了。这是因为 Spring 在不同的事务管理上定义了一个抽象层。我们无需了解底层的API,就可以使用Spring的事务管理。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  9. <context:component-scan base-package="com.itdragon.spring"></context:component-scan>
  10. <!-- 导入资源文件 -->
  11. <context:property-placeholder location="classpath:db.properties"/>
  12. <!-- 配置 C3P0 数据源 -->
  13. <bean id="dataSource"
  14. class="com.mchange.v2.c3p0.ComboPooledDataSource">
  15. <property name="user" value="${jdbc.user}"></property>
  16. <property name="password" value="${jdbc.password}"></property>
  17. <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
  18. <property name="driverClass" value="${jdbc.driverClass}"></property>
  19. <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
  20. <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
  21. </bean>
  22. <!-- 配置 Spirng 的 JdbcTemplate -->
  23. <bean id="jdbcTemplate"
  24. class="org.springframework.jdbc.core.JdbcTemplate">
  25. <property name="dataSource" ref="dataSource"></property>
  26. </bean>
  27. <!-- 配置 NamedParameterJdbcTemplate, 该对象可以使用具名参数, 其没有无参数的构造器, 所以必须为其构造器指定参数 -->
  28. <bean id="namedParameterJdbcTemplate"
  29. class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
  30. <constructor-arg ref="dataSource"></constructor-arg>
  31. </bean>
  32. <!-- 配置事务管理器 -->
  33. <bean id="transactionManager"
  34. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  35. <property name="dataSource" ref="dataSource"></property>
  36. </bean>
  37. <!-- 启用事务注解 如果配置的事务管理器的id就是transactionManager , 这里是可以省略transaction-manager -->
  38. <tx:annotation-driven transaction-manager="transactionManager"/>
  39. </beans>

接下来是事务的业务代码,所有类都放在了一个目录下,没别的原因,就是因为懒。

核心是消费事务类 PurchaseService。介绍事务注解@Transactional的语法。

其次是批量消费事务类BatchPurchaseService。用于配合PurchaseService测试事务的传播性。

然后是事务测试类TransactionTest。主要负责测试和详细解释事务语法。

最后是自定义异常类。是为了测试事务的回滚属性。

PurchaseService(重点,注解语法),测试时,将注解逐一放开。

  1. import java.util.List;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.annotation.Isolation;
  5. import org.springframework.transaction.annotation.Propagation;
  6. import org.springframework.transaction.annotation.Transactional;
  7. @Service
  8. public class PurchaseService {
  9. @Autowired
  10. private ShopDao shopDao;
  11. /**
  12. * 模拟用户购买商品,测事务回滚
  13. * 最基本用法,直接在方法或者类上使用注解@Transactional。值得注意的是:只能在公共方法上使用
  14. * 对应的测试方法是 basicTransaction()
  15. */
  16. @Transactional
  17. /**
  18. * 事务的传播 propagation=Propagation.REQUIRED
  19. * 常用的有两种 REQUIRED,REQUIRES_NEW
  20. * 对应的测试方法是 propagationTransaction()
  21. */
  22. // @Transactional(propagation=Propagation.REQUIRED)
  23. /**
  24. * 事务的隔离性
  25. * 将事务隔离起来,减少在高并发的场景下发生 脏读,幻读和不可重复读的问题
  26. * 默认值是READ_COMMITTED 只能避免脏读的情况。
  27. * 不好演示,没有对应的测试方法。
  28. */
  29. // @Transactional(isolation=Isolation.READ_COMMITTED)
  30. /**
  31. * 回滚事务属性
  32. * 默认情况下声明式事务对所有的运行时异常进行回滚,也可以指定某些异常回滚和某些异常不回滚。(意义不大)
  33. * noRollbackFor 指定异常不回滚
  34. * rollbackFor 指定异常回滚
  35. */
  36. // @Transactional(noRollbackFor={UserException.class, ProductException.class})
  37. /**
  38. * 超时和只读属性
  39. * 超时:在指定时间内没有完成事务则回滚。可以减少资源占用。参数单位是秒
  40. * 如果超时,则提示错误信息:
  41. * org.springframework.transaction.TransactionTimedOutException: Transaction timed out
  42. * 只读属性:指定事务是否为只读. 若事务只读数据则有利于数据库引擎优化事务。
  43. * 因为该事务有修改数据的操作,若设置只读true,则提示错误信息
  44. * nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
  45. * 对应的测试方法是 basicTransaction()
  46. */
  47. // @Transactional(timeout=5, readOnly=false)
  48. public void purchase(String account, String sku) {
  49. //1. 获取书的单价
  50. float price = shopDao.getBookPriceBySku(sku);
  51. //2. 更新数的库存
  52. shopDao.updateBookStock(sku);
  53. //3. 更新用户余额
  54. shopDao.updateUserBalance(account, price);
  55. // 测试超时用的
  56. /*try {
  57. Thread.sleep(6000);
  58. } catch (InterruptedException e) {
  59. }*/
  60. }
  61. }

批量消费事务类BatchPurchaseService

  1. import java.util.List;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.annotation.Transactional;
  5. @Service
  6. public class BatchPurchaseService {
  7. @Autowired
  8. private PurchaseService purchaseService;
  9. // 批量采购书籍,事务里面有事务
  10. @Transactional
  11. public void batchPurchase(String username, List<String> skus) {
  12. for (String sku : skus) {
  13. purchaseService.purchase(username, sku);
  14. }
  15. }
  16. }

事务测试类TransactionTest(重点,知识点说明

  1. import java.util.Arrays;
  2. import org.junit.Test;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class TransactionTest {
  6. private ApplicationContext ctx = null;
  7. private PurchaseService purchaseService = null;
  8. private BatchPurchaseService batchPurchaseService = null;
  9. {
  10. ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  11. purchaseService = (PurchaseService) ctx.getBean("purchaseService");
  12. batchPurchaseService = (BatchPurchaseService) ctx.getBean("batchPurchaseService");
  13. }
  14. /**
  15. * 用户买一本书
  16. * 基本用法-事务回滚
  17. * 把@Transactional 注释。假设当前用户余额只有10元。单元测试后,用户余额没有变,spring的库存却减少了。赚了!!!
  18. * 把@Transactional 注释打开。假设当前用户余额只有10元。单元测试后,用户余额没有变,spring的库存也没有减少。这就是回滚。
  19. * 回滚:按照业务逻辑,先更新库存,再更新余额。现在是库存更新成功了,但在余额逻辑抛出异常。最后数据库的值都没有变。也就是库存回滚了。
  20. */
  21. @Test
  22. public void basicTransaction() {
  23. System.out.println("^^^^^^^^^^^^^^^^^@Transactional 最基本的使用方法");
  24. purchaseService.purchase("itdragon", "spring");
  25. }
  26. /**
  27. * 用户买多本书
  28. * 事务的传播性 -大事务中,有小事务,小事务的表现形式
  29. * 用@Transactional, 当前用户余额50,是可以买一本书的。运行结束后,数据库中用户余额并没有减少,两本书的库存也都没有减少。
  30. * 用@Transactional(propagation=Propagation.REQUIRED), 运行结果是一样的。
  31. * 把REQUIRED 换成 REQUIRES_NEW 再运行 结果还是一样。。。。。
  32. * 为什么呢???? 因为我弄错了!!!!!
  33. * 既然是事务的传播性,那当然是一个事务传播给另一个事务。
  34. * 需要新增一个事务类批量购买 batchPurchase事务, 包含了purchase事务。
  35. * 把 REQUIRED 换成 REQUIRES_NEW 运行的结果是:用户余额减少了,第一本书的库存也减少了。
  36. * REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行。否则,就启动一个新的事务,并在自己的事务内运行。大事务回滚了,小事务跟着一起回滚。
  37. * REQUIRES_NEW:当前的方法必须启动新事务,并在自己的事务内运行。如果有事务在运行,应该将它挂起。大事务虽然回滚了,但是小事务已经结束了。
  38. */
  39. @Test
  40. public void propagationTransaction() {
  41. System.out.println("^^^^^^^^^^^^^^^^^@Transactional(propagation) 事务的传播性");
  42. batchPurchaseService.batchPurchase("itdragon", Arrays.asList("java", "spring"));
  43. }
  44. /**
  45. * 测试异常不回滚,故意超买(不常用)
  46. * 当前用户余额10元,买了一本价值40元的java书。运行结束后,余额没有少,java书的库存减少了(赚了!)。因为设置指定异常不回滚!
  47. * 指定异常回滚就不测了。
  48. */
  49. @Test
  50. public void noRollbackForTransaction() {
  51. System.out.println("^^^^^^^^^^^^^^^^^@Transactional(noRollbackFor) 设置回滚事务属性");
  52. purchaseService.purchase("itdragon", "java");
  53. }
  54. }

业务处理接口以及接口实现类

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Repository;
  4. @Repository("shopDao")
  5. public class ShopDaoImpl implements ShopDao {
  6. @Autowired
  7. private JdbcTemplate jdbcTemplate;
  8. @Override
  9. public float getBookPriceBySku(String sku) {
  10. String sql = "SELECT price FROM product WHERE sku = ?";
  11. /**
  12. * 第二个参数要用封装数据类型,如果用float.class,会提示 Type mismatch affecting row number 0 and column type 'FLOAT':
  13. * Value [40.0] is of type [java.lang.Float] and cannot be converted to required type [float] 错误
  14. */
  15. return jdbcTemplate.queryForObject(sql, Float.class, sku);
  16. }
  17. @Override
  18. public void updateBookStock(String sku) {
  19. // step1 防超卖,购买前先检查库存。若不够, 则抛出异常
  20. String sql = "SELECT stock FROM product WHERE sku = ?";
  21. int stock = jdbcTemplate.queryForObject(sql, Integer.class, sku);
  22. System.out.println("^^^^^^^^^^^^^^^^^商品( " + sku + " )可用库存 : " + stock);
  23. if(stock == 0){
  24. throw new ProductException("库存不足!再看看其他产品吧!");
  25. }
  26. // step2 更新库存
  27. jdbcTemplate.update("UPDATE product SET stock = stock -1 WHERE sku = ?", sku);
  28. }
  29. @Override
  30. public void updateUserBalance(String account, float price) {
  31. // step1 下单前验证余额是否足够, 若不足则抛出异常
  32. String sql = "SELECT balance FROM user WHERE account = ?";
  33. float balance = jdbcTemplate.queryForObject(sql, Float.class, account);
  34. System.out.println("^^^^^^^^^^^^^^^^^您当前余额 : " + balance + ", 当前商品价格 : " + price);
  35. if(balance < price){
  36. throw new UserException("您的余额不足!不支持购买!");
  37. }
  38. // step2 更新用户余额
  39. jdbcTemplate.update("UPDATE user SET balance = balance - ? WHERE account = ?", price, account);
  40. // step3 查看用于余额
  41. System.out.println("^^^^^^^^^^^^^^^^^您当前余额 : " + jdbcTemplate.queryForObject(sql, Float.class, account));
  42. }
  43. }

最后两个自定义的异常类

  1. public class UserException extends RuntimeException{
  2. private static final long serialVersionUID = 1L;
  3. public UserException() {
  4. super();
  5. }
  6. public UserException(String message) {
  7. super(message);
  8. }
  9. }
  1. public class ProductException extends RuntimeException{
  2. private static final long serialVersionUID = 1L;
  3. public ProductException() {
  4. super();
  5. }
  6. public ProductException(String message) {
  7. super(message);
  8. }
  9. }

当用户余额10元不够买售价为50的书,书的库存充足的情况。测试basicTransaction()方法打印的结果:用户余额不减少,库存也不减少

当用户余额50元准备购买两本总价为90的书,但余额只够买一本书,书的库存充足的情况,测试propagationTransaction()方法打印的结果:若用 REQUIRES_NEW则两本中可以买一本;若用REQUIRED则一本都买不了。(事务的传播性有7种,这里主要介绍常用的REQUIRED和REQUIRES_NEW)

当用户余额10元不够买售价40元的书,书的库存充足的情况。测试noRollbackForTransaction()方法打印的结果:用户余额没有减少,但商品库存减少了,说明事务没有回滚。

细细品味后,其实也很简单。事务就是为了保证数据的一致性。出了问题就把之前修改过的数据回滚。


基于xml的事务管理

如果你理解了基于注解的事务管理,那基于xml的事务管理就简单多了。由于篇幅已经太长了,这里我长话短说。

首先把上面的java类中的所有IOC注解,@Transactional注解和@Autowired去掉。被@Autowired修饰的属性,还需要另外生成setter方法。

然后配置applicationContext.xml文件。将启动事务注解的代码删掉。将之前用自动扫描包的IOC注解和@Autowired注解的代码都配置bean(IOC知识),然后 配置事务属性,最后 配置事务切入点(AOP知识),这是系列博客,不懂的可以看前面几章。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
  9. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  10. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  11. <!-- 导入资源文件 -->
  12. <context:property-placeholder location="classpath:db.properties"/>
  13. <!-- 配置 C3P0 数据源 -->
  14. <bean id="dataSource"
  15. class="com.mchange.v2.c3p0.ComboPooledDataSource">
  16. <property name="user" value="${jdbc.user}"></property>
  17. <property name="password" value="${jdbc.password}"></property>
  18. <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
  19. <property name="driverClass" value="${jdbc.driverClass}"></property>
  20. <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
  21. <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
  22. </bean>
  23. <!-- 配置 Spirng 的 JdbcTemplate -->
  24. <bean id="jdbcTemplate"
  25. class="org.springframework.jdbc.core.JdbcTemplate">
  26. <property name="dataSource" ref="dataSource"></property>
  27. </bean>
  28. <!-- 配置 NamedParameterJdbcTemplate, 该对象可以使用具名参数, 其没有无参数的构造器, 所以必须为其构造器指定参数 -->
  29. <bean id="namedParameterJdbcTemplate"
  30. class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
  31. <constructor-arg ref="dataSource"></constructor-arg>
  32. </bean>
  33. <bean id="shopDao" class="com.itdragon.spring.my.transactionxml.ShopDaoImpl">
  34. <property name="jdbcTemplate" ref="jdbcTemplate"></property>
  35. </bean>
  36. <bean id="purchaseService" class="com.itdragon.spring.my.transactionxml.PurchaseService">
  37. <property name="shopDao" ref="shopDao"></property>
  38. </bean>
  39. <bean id="batchPurchaseService" class="com.itdragon.spring.my.transactionxml.BatchPurchaseService">
  40. <property name="purchaseService" ref="purchaseService"></property>
  41. </bean>
  42. <!-- 配置事务管理器 -->
  43. <bean id="transactionManager"
  44. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  45. <property name="dataSource" ref="dataSource"></property>
  46. </bean>
  47. <!-- 配置事务属性 -->
  48. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  49. <tx:attributes>
  50. <!-- 根据方法名指定事务的属性 -->
  51. <tx:method name="purchase"
  52. propagation="REQUIRES_NEW"
  53. timeout="3"
  54. read-only="false"/>
  55. <tx:method name="batchPurchase"/>
  56. </tx:attributes>
  57. </tx:advice>
  58. <!-- 配置事务切入点 -->
  59. <aop:config>
  60. <aop:pointcut expression="execution(* com.itdragon.spring.my.transactionxml.PurchaseService.purchase(..))"
  61. id="pointCut"/>
  62. <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
  63. </aop:config>
  64. <aop:config>
  65. <aop:pointcut expression="execution(* com.itdragon.spring.my.transactionxml.BatchPurchaseService.batchPurchase(..))"
  66. id="batchPointCut"/>
  67. <aop:advisor advice-ref="txAdvice" pointcut-ref="batchPointCut"/>
  68. </aop:config>
  69. </beans>

代码亲测可用。有什么错误地方可以指出。

到这里Spring4 的教程也就结束了。感谢您的观看!!!

Spring4 事务管理的更多相关文章

  1. Spring4笔记9--Spring的事务管理(AOP应用的例子)

    Spring的事务管理: 事务原本是数据库中的概念,在 Dao 层.但一般情况下,需要将事务提升到业务层,即 Service 层.这样做是为了能够使用事务的特性来管理具体的业务.   在 Spring ...

  2. Hibernate与Spring的事务管理

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

  3. Spring 事务管理案例

    事务管理简介   Spring 事务管理有两种方式:一种是编程式事务管理,即通过编写代码实现事物管理,包括定义事务的开始,程序正常执行后的事物提交,异常时进行的事务回滚.另一种是基于AOP技术实现的声 ...

  4. Spring事务管理配置以及异常处理

    Spring事务管理配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...

  5. Spring Boot -- Spring Boot之@Async异步调用、Mybatis、事务管理等

    这一节将在上一节的基础上,继续深入学习Spring Boot相关知识,其中主要包括@Async异步调用,@Value自定义参数.Mybatis.事务管理等. 本节所使用的代码是在上一节项目代码中,继续 ...

  6. Spring Framework之事务管理

    目录 问题 数据库事务 事务的定义 事务的目的 事务的特性 事务隔离级别 数据并发问题 事务隔离级别对数据并发问题的作用 快照读 Spring事务管理 事务管理接口 TransactionDefini ...

  7. Spring—SSJ集成&声明式事务管理

    1.   课程介绍 1.  SSJ集成;(掌握) 2.  声明式事务管理;(掌握) 什么是三大框架 2.1.  ssh Struts/Struts2 Spring Hibernate 2.2.  ss ...

  8. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  9. spring声明式事务管理总结

    事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...

随机推荐

  1. C#仪器数据文件解析-Word文件(doc、docx)

    不少仪器数据报告输出为Word格式文件,同Excel文件,Word文件doc和docx的存储格式是不同的,相应的解析Word文件的方式也类似,主要有以下方式: 1.通过MS Word应用程序的DCOM ...

  2. 谦先生的bug日志之hive启动权限问题

    上海尚学堂谦先生的bug日志之hive启动权限问题 这几天开始做新老集群的迁移,今天开始对hive的所有数据进行迁移,主要是表的元信息和表数据.表的元信息我们存在mysql中,跟hive的服务器并不在 ...

  3. Mysql [Err] 1293 there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    问题: mysql数据 导入数据出错 [Err] 1293 - Incorrect table definition; there can be only one TIMESTAMP column w ...

  4. HTML5之indexedDB

    从陌生到了解,花了一下午的时间,以下的地址还是不错的参考资料,省的到处去找 HTML5本地存储——IndexedDB(一:基本使用) 官方API接口文档 官方使用示例 html5 初试 indexed ...

  5. VS连接数据库的通用方法(SQL/MySql)

    在vs里面连接数据库的方法有很多,这里是通用的方法和基本操作 SQL /// <summary> /// 数据访问抽象基础类 /// Copyright (C) Maticsoft /// ...

  6. Java并发之CountDownLatch、CyclicBarrier和Semaphore

    CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑:CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务. CountDow ...

  7. python异步并发模块concurrent.futures入门详解

    concurrent.futures是一个非常简单易用的库,主要用来实现多线程和多进程的异步并发. 本文主要对concurrent.futures库相关模块进行详解,并分别提供了详细的示例demo. ...

  8. [Bayesian] “我是bayesian我怕谁”系列 - Exact Inferences

    要整理这部分内容,一开始我是拒绝的.欣赏贝叶斯的人本就不多,这部分过后恐怕就要成为“从入门到放弃”系列. 但,这部分是基础,不管是Professor Daphne Koller,还是统计学习经典,都有 ...

  9. 编译错误:expected an indented block

    python 对缩进要求非常严格,当运行时出现以下几种情况时,就需要修改缩进: 1.expected an indented block 直接缩进4个space空格或者一个tab.

  10. Azure 基础 : 使用 template 简化部署

    笔者在前文中介绍了如何使用 PowerShell 脚本在 Azure 上创建虚拟主机.正如你所看到的,整个创建过程还是有点繁琐的,因为我们需要使用 PowerShell 脚本创建并关联所有相关的组件. ...