Spring Data JPA事务管理

1、事务基础概念_四大特性

 数据库中事务的四大特性(ACID),如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性:

 ⑴ 原子性(Atomicity)

  原子性,是指事务包含的所有操作,要么全部成功,要么全部失败回滚。因此,事务的操作如果成功就必须要完全持久化到数据库,如果操作失败则不能对数据库有任何影响。

 ⑵ 一致性(Consistency)

  一致性,是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  举例:假设用户甲和用户乙两者的钱加起来一共是10000,那么不管甲和乙之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还是10000,这即是事务的一致性。

 ⑶ 隔离性(Isolation)

  隔离性,是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

       在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

       第一、脏读

  脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。

  当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:用户A向用户B转账100元,对应SQL命令如下

    update account set money=money+100 where name=’B’;  (此时A通知B)update account set money=money - 100 where name=’A’;


  当只执行第一条SQL时,A通知B查看账户,B发现确实钱已到账(此时即发生了脏读),而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,那么当B以后再次查看账户时就会发现钱其实并没有转。

       第二、不可重复读

  不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

  例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。

  不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

  在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……

       第三、虚读(幻读)

  幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

  幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)

  关于事务的隔离性数据库提供了多种隔离级别,mySQL数据库为我们提供的四种隔离级别:

  ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

  ③ Read committed (读已提交):可避免脏读的发生。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

     以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

  在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

查看mysql数据库事务的默认隔离级别

SELECT @@tx_isolation;

 ⑷ 持久性(Durability)

  持久性,是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

  例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

2、spring-data-jpa事务管理

1)默认事务

   Spring Data 提供了默认的事务处理方式,即所有的查询均声明为只读事务。确保了单个请求过程数据的一致性。

  对于自定义的方法,如需改变 SpringData 提供的事务默认方式,可以在方法上注解@Transactional声明进行多个 Repository操作时,也应该使它们在同一个事务中处理,按照分层架构的思想,这部分属于业务逻辑层,因此,需要在Service 层实现对多个 Repository的调用,并在相应的方法上声明事务。 

    Repository概念:按照最初提出者的介绍,它是衔接数据映射层和域之间的一个纽带,作用相当于一个在内存中的域对象集合。客户端对象把查询的一些实体进行组合,并把它们提交给Repository。对象能够从Repository中移除或者添加,就好比这些对象在一个Collection对象上就行数据操作,同时映射层的代码会对应的从数据库中取出相应的数据。

    从概念上讲,Repository是把一个数据存储区的数据给封装成对象的集合并提供了对这些集合的操作。

    广义上可以理解为我们常说的DAO

2)dao层代码

@Modifying
@Query(value="UPDATE hr_employee_contract t SET t.deleteStatus=1 WHERE t.id=?1",nativeQuery = true)
void delete(Long id);

说明:@Modifying注解

①在@Query注解中,编写JPQL实现DELETE和UPDATE操作的时候,必须加上@modifying注解,以通知Spring Data 这是一个DELETE或UPDATE操作。

②UPDATE或者DELETE操作需要使用事务,此时需要定义Service层,在Service层的方法上添加事务操作。

③注意JPQL不支持INSERT操作。 

3)service层代码

使用@Transactional手动开启事务管理

@Transactional
@Override
public void delete(Long id) {employeeContractDao.delete(id);
}

@Transactional注解支持9个属性的设置,其中使用较多的三个属性:readOnly、propagation、isolation。其中propagation属性用来枚举事务的传播行为,isolation用来设置事务隔离级别,readOnly进行读写事务控制。

① readOnly

从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)

应用场合:

NO.1、如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 
NO.2、如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】

怎样设置:

对于只读查询,可以指定事务类型为readonly,即只读事务。
由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。

(1)在JDBC中,指定只读事务的办法为: connection.setReadOnly(true);

(2)在Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER); 
此时,Hibernate也会为只读事务提供Session方面的一些优化手段

(3)在Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“readOnly”
或者用注解方式@Transactional(readOnly=true)
【 if the transaction is marked as read-only, Spring will set the Hibernate Session’s flush mode to FLUSH_NEVER, 
and will set the JDBC transaction to read-only】也就是说在Spring中设置只读事务是利用上面两种方式

② propagation

//支持当前事务,如果当前没有事务,就新建一个事务。Spring默认事务级别。
int PROPAGATION_REQUIRED = 0;  //支持当前事务,如果当前没有事务,就以非事务方式执行。
int PROPAGATION_SUPPORTS = 1;  //支持当前事务,如果当前没有事务,就抛出异常。
int PROPAGATION_MANDATORY = 2;  //新建事务,如果当前存在事务,把当前事务挂起。执行新事务后,再激活当前事务。
int PROPAGATION_REQUIRES_NEW = 3;  //以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
int PROPAGATION_NOT_SUPPORTED = 4;  //以非事务方式执行,如果当前存在事务,则抛出异常。
int PROPAGATION_NEVER = 5;//如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。//嵌套时由外部事务决定,子事务是否是commit还是rollback。//一般在外部事务是使用try{}catch(嵌套事务方法){}进行编码。
int PROPAGATION_NESTED = 6; 

案例分析1:

@Service
class A{@AutowiredB b;@Transactional(propagation = Propagation.REQUIRED)    void call(){try{b.call();} catch(Exception e){//doSomething....//不抛异常,则A无法提交}//doSomething....}
}@Service
class B{@Transactional(propagation = Propagation.REQUIRED)void call(){}
}

A和B共用事务,如果B异常。A未使用try..catch..捕获,则AB一起回滚。

如果B异常。A捕获,但并未抛出。则A最终也无法提交,因为B的事务已经被设置为rollback-only了。

案例分析2:

@Service
class A{@AutowiredB b;@Transactional(propagation = Propagation.REQUIRED)    void call(){try{b.call();} catch(Exception e){throw e; //或者不抛}//doSomething....}
}@Service
class B{@Transactional(propagation = Propagation.REQUIRES_NEW)void call(){}
}

执行b.call()时A事务挂起,此时如果B执行异常。被A捕获,如果抛出异常,则AB回滚;如果A捕获未抛异常,则A继续执行不回滚。

执行b.call()时A事务挂起,此时如果B正常执行,而在A中出现异常。则B不回滚,A回滚。

案例分析3:

@Service
class A{@AutowiredB b;@Transactional(propagation = Propagation.REQUIRED)    void call(){try{b.call();} catch(Exception e){throw e; //或者不抛}//doSomething....}
}@Service
class B{@Transactional(propagation = Propagation.NESTED)void call(){}
}

执行b.call()时A事务挂起,B新起事务并设置SavePoint。如果B正常执行,A出现异常,则AB一起回滚。

如果B失败异常,此时A如果捕获但未抛出,后续A正常执行的话,A可以提交,而B已经回滚。

如果B失败异常,此时A如果捕获且抛出,则AB一起回滚。

以上案例,我们可以得出第1种和第3种模式的区别,第3种在嵌套模式下,可以在内部异常下执行其它业务且外部正常提交,而第1种不可以这么操作。

③ isolation 

    @Override@Transactional(isolation = Isolation.READ_COMMITTED)public void test() {User user = userMapper.getOne(1L);System.out.println(user.getName());userMapper.updateUser();try {Thread.sleep(10000); // 10 s} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end");}

@Transactional 默认值

3、spring事务详解

    Spring 为事务管理提供了丰富的功能支持。

    Spring 事务管理分为编码式声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。

    声明式事务有两种方式:一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式。注释配置是目前流行的使用方式,此处重介绍基于@Transactional 注解的事务管理。

1)@Transactional 注解管理事务的实现步骤

使用@Transactional 注解管理事务的实现步骤分为两步。

第一步,配置

在 xml 配置类或配置文件中添加如的事务配置信息。除了用配置文件的方式,@EnableTransactionManagement 注解也可以启用事务管理功能。这里以简单的 DataSourceTransactionManager 为例。

1、配置类

 

package com.myfutech.market.service.provider.config;import com.myfutech.common.spring.jpa.base.impl.BaseJpaRepositoryImpl;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.util.Properties;@Configuration
@ConditionalOnClass(HikariDataSource.class)
@EnableConfigurationProperties(ConnectionPoolProperties.class)
@EnableJpaRepositories(entityManagerFactoryRef = "marketServiceEntityManagerFactory",transactionManagerRef = "marketServiceTransactionManager", basePackages="com.myfutech.market.service.provider.dao",repositoryBaseClass = BaseJpaRepositoryImpl.class)
public class JpaConfig {@Value("${marketService.url}")private String url;@Value("${marketService.username}")private String username;@Value("${marketService.password}")private String password;@Autowiredprivate ConnectionPoolProperties properties;@Bean("marketServiceTransactionManager")PlatformTransactionManager marketServiceTransactionManager() {return new JpaTransactionManager(marketServiceEntityManagerFactory().getObject());}@Bean("marketServiceEntityManagerFactory")LocalContainerEntityManagerFactoryBean marketServiceEntityManagerFactory() {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();Properties properties = new Properties();properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");properties.setProperty("hibernate.jdbc.batch_size", "20");properties.setProperty("current_session_context_class", "jpa");properties.setProperty("hibernate.ejb.entitymanager_factory_name", "marketServiceEntityManagerFactory");properties.setProperty("hibernate.hbm2ddl.auto", "none");factoryBean.setJpaProperties(properties);factoryBean.setDataSource(marketServiceDataSource());factoryBean.setJpaVendorAdapter(vendorAdapter);factoryBean.setPackagesToScan("com.myfutech.market.service.provider.model");return factoryBean;}@BeanJdbcTemplate initJdbcTemplate(){return new JdbcTemplate(marketServiceDataSource());}@Bean("marketServiceDataSource")DataSource marketServiceDataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setJdbcUrl(url);dataSource.setDriverClassName(properties.getDriverClass());dataSource.addDataSourceProperty("cachePrepStmts", properties.isCachePrepStmts());dataSource.addDataSourceProperty("prepStmtCacheSize", properties.getPrepStmtCacheSize());dataSource.addDataSourceProperty("prepStmtCacheSqlLimit", properties.getPrepStmtCacheSqlLimit());dataSource.addDataSourceProperty("useServerPrepStmts", properties.isUseServerPrepStmts());dataSource.addDataSourceProperty("useLocalSessionState", properties.isUseLocalSessionState());dataSource.addDataSourceProperty("rewriteBatchedStatements", properties.isRewriteBatchedStatements());dataSource.addDataSourceProperty("cacheResultSetMetadata", properties.isCacheResultSetMetadata());dataSource.addDataSourceProperty("cacheServerConfiguration", properties.isCacheServerConfiguration());dataSource.addDataSourceProperty("elideSetAutoCommits", properties.isElideSetAutoCommits());dataSource.addDataSourceProperty("maintainTimeStats", properties.isMaintainTimeStats());return dataSource;}
}

2、或者在 xml 配置中的事务配置信息 

清单1

<tx:annotation-driven /><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />
</bean>


第二步,添加

将@Transactional 注解添加到合适的方法上,并设置合适的属性信息。@Transactional 注解的属性信息如表 1 展示。

表 1. @Transactional 注解的属性信息

① @Transactional 注解也可添加在类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。如下面类,EmployeeService 的所有方法都支持事务并且是只读。

② 当类级别配置了@Transactional,方法级别也配置了@Transactional,应用程序会以方法级别的事务属性信息来管理事务,换言之,方法级别的事务属性信息会覆盖类级别的相关配置信息。

@Transactional 注解的类级别支持

清单 2

@Transactional(propagation= Propagation.SUPPORTS,readOnly=true)
@Service(value ="employeeService")
public class EmployeeService

        到此,您会发觉使用@Transactional 注解管理事务的实现步骤很简单。但是如果对 Spring 中的 @transaction 注解的事务管理理解的不够透彻,就很容易出现错误,比如事务应该回滚(rollback)而没有回滚事务的问题。接下来,将首先分析 Spring 的注解方式的事务实现机制,然后列出相关的注意事项,以最终达到帮助开发人员准确而熟练的使用 Spring 的事务的目的。

2)Spring 的注解方式的事务实现机制

        在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据@Transactional 的属性配置信息,这个代理对象决定该声明@Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器(图 2 有相关介绍)AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务, 如图 1 所示。

                                                               图 1. Spring 事务实现机制

        Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 两种,图 1 是以 CglibAopProxy 为例,对于 CglibAopProxy,需要调用其内部类的 DynamicAdvisedInterceptor 的 intercept 方法。对于 JdkDynamicAopProxy,需要调用其 invoke 方法。

        正如上文提到的,事务管理的框架是由抽象事务管理器 AbstractPlatformTransactionManager 来提供的,而具体的底层事务处理实现,由 PlatformTransactionManager 的具体实现类来实现,如事务管理器 DataSourceTransactionManager。不同的事务管理器管理不同的数据资源 DataSource,比如 DataSourceTransactionManager 管理 JDBC 的 Connection。

PlatformTransactionManager,AbstractPlatformTransactionManager 及具体实现类关系如图 2 所示。

                                                            图 2. TransactionManager 类结构

3)注解方式的事务使用注意事项

    当您对 Spring 的基于注解方式的实现步骤和事务内在实现机制有较好的理解之后,就会更好的使用注解方式的事务管理,避免当系统抛出异常,数据不能回滚的问题。

正确的设置@Transactional 的 propagation 属性

需要注意下面三种 propagation 可以不启动事务。本来期望目标方法进行事务管理,但若是错误的配置这三种 propagation,事务将不会发生回滚。

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

正确的设置@Transactional 的 rollbackFor 属性

默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。

如果在事务中抛出其他类型的异常,并期望 Spring 能够回滚事务,可以指定 rollbackFor。例:

@Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class)

通过分析 Spring 源码可以知道,若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。

清单 3. RollbackRuleAttribute 的 getDepth 方法

private int getDepth(Class<?> exceptionClass, int depth) {if (exceptionClass.getName().contains(this.exceptionName)) {// Found it!return depth;}// If we've gone as far as we can go and haven't found it...if (exceptionClass == Throwable.class) {return -1;}return getDepth(exceptionClass.getSuperclass(), depth + 1);}


@Transactional 只能应用到 public 方法才有效

只有@Transactional 注解应用到 public 方法,才能进行事务管理。这是因为在使用 Spring AOP 代理时,Spring 在调用在图 1 中的 TransactionInterceptor 在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取表 1. @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。

清单 4. AbstractFallbackTransactionAttributeSource

protected TransactionAttribute computeTransactionAttribute(Method method,Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}

这个方法会检查目标方法的修饰符是不是 public,若不是 public,就不会获取@Transactional 的属性配置信息,最终会造成不会用 TransactionInterceptor 来拦截该目标方法进行事务管理。

避免 Spring 的 AOP 的自调用问题

在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚。见清单 5 举例代码展示。

清单 5.自调用问题举例

    @Servicepublic class OrderService {private void insert() {insertOrder();}@Transactionalpublic void insertOrder() {//insert log info//insertOrder//updateAccount}}

insertOrder 尽管有@Transactional 注解,但它被内部方法 insert 调用,事务被忽略,出现异常事务不会发生回滚。

上面的两个问题@Transactional 注解只应用到 public 方法和自调用问题,是由于使用 Spring AOP 代理造成的。为解决这两个问题,使用 AspectJ 取代 Spring AOP 代理。

需要将下面的 AspectJ 信息添加到 xml 配置信息中。

清单 6. AspectJ 的 xml 配置信息

<tx:annotation-driven mode="aspectj" /><bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />
</bean><bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf"><property name="transactionManager" ref="transactionManager" />
</bean>

同时在 Maven 的 pom 文件中加入 spring-aspects 和 aspectjrt 的 dependency 以及 aspectj-maven-plugin。

清单 7. AspectJ 的 pom 配置信息

<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.3.2.RELEASE</version>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version>
</dependency>
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>aspectj-maven-plugin</artifactId><version>1.9</version><configuration><showWeaveInfo>true</showWeaveInfo><aspectLibraries><aspectLibrary><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></aspectLibrary></aspectLibraries></configuration><executions><execution><goals><goal>compile</goal><goal>test-compile</goal></goals></execution></executions>
</plugin>


 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

教育部发文:AI、算法等2018年进入全国高中课程!

来源&#xff1a;全球人工智能概要&#xff1a;1月16日上午&#xff0c;教育部召开新闻发布会&#xff0c;介绍了《普通高中课程方案和语文等学科课程标准&#xff08;2017年版&#xff09;》的有关情况&#xff0c;并重新修订了语文等14门学科的课程标准。1月16日上午&#xf…

JPA事务示例分析

在这个工程中&#xff0c;定义一个名为User的实体&#xff1a; Entity Data NoArgsConstructor public class User {IdGeneratedValueprivate Long id;Size(max 5)private String name;Max(50)private Integer age;public User(String name, Integer age) {this.name name;t…

智能零售来了!Amazon Go无人商店周一正式对公众开放

来源&#xff1a;网络大数据概要&#xff1a;经过近 14 个月只对亚马逊公司员工开放的试运行&#xff0c;周一这家标着 Amazon Go 标志的店面将公开亮相&#xff0c;这是亚马逊近年来投入最多努力的项目之一&#xff0c;旨在重塑实体购物的体验。据《西雅图时报》报道&#xff…

看懂GE Predix ,就看懂了工业互联网

来源&#xff1a;小黑羊JoinWings概要&#xff1a;Predix是GE推出的针对整个工业领域的基础性系统平台&#xff0c;这是一个开放的平台&#xff0c;它可以应用在工业制造、能源、医疗等各个领域。Predix是GE推出的针对整个工业领域的基础性系统平台&#xff0c;这是一个开放的平…

JPA和事务管理

1 事务 1.1事务管理方式 spring支持编程式事务管理和声明式事务管理两种方式。 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理&#xff0c;spring推荐使用TransactionTemplate。 声明式事务管理建立在AOP之上的…

纽约大学Gary Marcus发文指出AlphaZero「被夸大」,强调重视人工智能「先天因素」

原文来源&#xff1a;arXiv作者&#xff1a;Gary Marcus「雷克世界」编译&#xff1a;嗯~是阿童木呀纽约大学Gary Marcus教授一直是深度学习的反对者&#xff0c;他认为深度学习并没有主动学习能力&#xff0c;且鲁棒性较差。同时&#xff0c;他始终认为人工智能应该多在“先天…

oracle10g新建数据,Oracle10g手工创建数据库

【注&#xff1a;本文中所有$表示在oracle用户中操作的命令、SQL>表示所有SQL语句】手工建库步骤&#xff1a;1、删除原有的数据库&#xff0c;如TEST命令&#xff1a;SQL> shutdown immediate;SQL> startup mount;SQL> alter system enable restricted session;SQ…

展望:模型驱动的深度学习

来源&#xff1a;《国家科学评论》概要&#xff1a;近年来&#xff0c;深度学习在人工智能领域一系列困难问题上取得了突破性成功应用。模型驱动的深度学习方法近年来&#xff0c;深度学习在人工智能领域一系列困难问题上取得了突破性成功应用。例如用于人脸识别已高于人的正确…

JPA架构

JPA(Java持久性API)是存储业务实体关联的实体的来源。它显示了如何定义一个面向普通Java对象(POJO)作为一个实体&#xff0c;以及如何与管理关系实体。 类级别架构 下图显示了JPA的类的层次结构。它显示核心类和JPA接口。 下表描述了每个在上述架构的显示单元。 单元描述Ent…

Amazon Go开门营业,号称无需现金、无需排队结账,现场究竟体验如何?

来源&#xff1a;36氪概要&#xff1a;无人零售的鼻祖Amazon Go姗姗来迟&#xff0c;那么体验究竟如何呢&#xff1f;无人零售的鼻祖Amazon Go姗姗来迟&#xff0c;那么体验究竟如何呢&#xff1f;当地时间周一&#xff08;1月22日&#xff09;&#xff0c;位于西雅图亚马逊总部…

哪些是Linux内核的同步机制,Linux内核的同步机制(1)

Linux内核的同步机制(1)yanqin | 2009-04-16 14:51:09 阅读&#xff1a;791发布文章一、 引言%A%A 在现代操作系统里&#xff0c;同一时间可能有多个内核执行流在执行&#xff0c;因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤…

量子机器学习入门科普:解读量子力学和机器学习的共生关系

原作&#xff1a;Reena Shaw安妮 编译自 KDnuggets量子位 出品 | 公众号 QbitAI量子机器学习&#xff08;Quantum ML&#xff09;是量子力学和机器学习的一门交叉学科。两者间像一种共生关系&#xff0c;我们可以利用量子计算的力量生成机器学习算法的量子版本&#xff0c;并应…

RedissonClient 缓存Bug

引入背景 期望RedissonClient 能定期更新&#xff0c;避免网络不稳定导致 Redis 连接失效&#xff0c;只能重启服务&#xff1f; 使用了Caffeine 缓存&#xff0c;自动 2 小时失效剔除RedissonClient /*** 本地缓存.*/private static final Cache<String, RedissonClient&g…

人工智能重构下的金融场景

来源&#xff1a;亿欧概要&#xff1a;从金融领域来看&#xff0c;国际银行业对人工智能的主要应用集中在资本运营、市场分析、客户营销、风险监管等方面。智能客服、智能投顾、智能量化交易……人工智能在金融领域存在巨大的发展空间&#xff0c;但其也使监管更加复杂。近年来…

linux中写脚本不能写中文,Linux系统中Sublime Text无法输入中文怎么办?

Sublime Text是一个代码编辑器&#xff0c;拥有强大的功能&#xff0c;但Sublime Text 在Linux下运行的时候存在无法输入中文的问题&#xff0c;遇到该问题该如何解决呢&#xff1f;下面小编就给大家介绍下Linux下Sublime Text 无法输入中文的解决方法。1.保存下面的代码为subl…

深度学习引擎的终极形态是什么?

来源&#xff1a;微软研究院AI头条概要&#xff1a;1月17日&#xff0c;院友袁进辉博士回到微软亚洲研究院做了题为《打造最强深度学习引擎》的报告&#xff0c;分享了深度学习框架方面的技术进展。1月17日&#xff0c;院友袁进辉博士回到微软亚洲研究院做了题为《打造最强深度…

linux进程映像由哪些构成,Linux编程开发进程映像类型分析

进程与线程问题是程序员在学习编程开发语言需要重点掌握的编程知识之一&#xff0c;而今天我们就一起来了解一下&#xff0c;Linux编程开发中进程映像的执行标准。什么是进程映像呢?进程映像是执行程序时所需要的可执行文件&#xff0c;通常会包括下面这些东西代码段(codesegm…

AI芯片之争白热化的当下,如何设计一款真正适用于终端的AI芯片?

来源&#xff1a;36氪概要&#xff1a;2017年&#xff0c;人工智能最火的风口一定是AI芯片。2017年&#xff0c;人工智能最火的风口一定是AI芯片。AI芯片的出现&#xff0c;与深度学习技术的成熟及应用密不可分。深度学习的过程可以简化理解为利用大量标注的数据进行训练&#…

李开复:AI巨头是有史以来最难以打破的垄断

来源&#xff1a;凤凰网概要&#xff1a;李开复认为目前最需要的是小的AI公司&#xff0c;甚至于打破巨头垄断局面的“破局者”也会是这些由小变大的AI公司。当地时间周二(1月23日)&#xff0c;世界经济论坛在瑞士达沃斯小镇正式举行&#xff0c;各国政要、企业家、学者云集。创…

杨立昆辞Facebook人工智能实验室主任,任首席科学家

来源&#xff1a;澎湃新闻概要&#xff1a;他将不再担任Facebook 人工智能实验室主任一职&#xff0c;改任Facebook首席人工智能科学家&#xff0c;从而能更加专注于带领科学研究与AI策略。当地时间1月23日&#xff0c;执掌Facebook人工智能实验室&#xff08;FAIR&#xff09;…