我需要以可靠/事务方式为外部系统排队事件和任务.使用像MSMQ或ActiveMQ这样的东西看起来非常诱人,但事务部分变得复杂(MSDTC等).
我们可以使用数据库(SQL Server 2005 +,Oracle 9+)并实现更简单的事务支持,但排队部分变得更加丑陋.
两条路线看起来都不那么好,并且充满了讨厌的陷阱和边缘情况.
有人可以在这个问题上提供一些实用指导吗?
想一想:E/C/A或计划任务引擎每隔一段时间就会唤醒并查看此时是否有任何需要运行的计划任务(即下一个运行日期已过,但到期日期尚未到期到达).
我知道我的问题是一个普遍的问题,但是我在这里检查了很多问题,检查了Spring文档,但我真的不知道我在做什么错。我的问题:我有一个使用JPA的Spring WebFlow项目(实现:OpenJPA + MySQL数据库)。我使用Spring ORM将EntityManager(通过@PersistenceContext注释)注入到我的简单RegisterDAO中。我已经配置了GlassFishs(正在使用的)连接池以使用MySQL,并且一切正常-我可以使用我的数据库,但是当我保留某些东西时-没有任何反应(数据未保留到数据库)。我知道问题出在我使用的事务上下文中。我阅读了Spring Transaction Management的文档,并按照本文档中的配置步骤进行操作。这是我的applicationContext.xml:
<?xml version="1.0" encoding="windows-1250"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<jee:jndi-lookup id="entityManagerFactory" jndi-name="myPersistenceUnit"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="registerDaoImpl" class="umk.dumont.db.dao.RegisterDAO" />
<bean id="registerModel" class="umk.dumont.models.RegisterFormModel">
<property name="registerDAO" ref="registerDaoImpl" />
</bean>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="registerModelOperation" expression="execution(* umk.dumont.models.RegisterFormModel.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="registerModelOperation"/>
</aop:config>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
</beans>
Run Code Online (Sandbox Code Playgroud)
如您所见,我正在将RegisterDAO注入我的RegisterFormModel中,其中包含我的业务逻辑,用于验证注册表单数据并最终将用户添加到数据库中。验证工作正常,当我尝试添加新用户时出现问题。这是代码:
package umk.dumont.models;
...
public class RegisterFormModel implements Serializable {
private String login;
private …Run Code Online (Sandbox Code Playgroud) 嗨,
我有一个hibernate实体,它有一组另一个实体作为其字段.像这样的东西:
public class UserEntity implements Srializable {
private Set<Role> roles;
}
Run Code Online (Sandbox Code Playgroud)
我应该以一种方式保留表,即系统中始终存在至少一个ADMIN用户.这可以通过简单的方式完成,如下所示:
public void updateUser{
UserEntity ue = getUser();
if (userIsNotTheLastAdmin(ue)) {
/** Here is a race condition **/
roles.remove(Role.ADMIN);
getSession().saveOrUpdate(ue);
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我们进行并发操作时会发生真正的问题.如何以原子方式执行所有操作?
谢谢,
HM
我已经两次问过这个问题,但我是stackoverflow的新手,似乎我不知道在这里格式化我的示例代码的规则.现在我决定给出完整的一堆电话,我希望我能解释一下这种情况,因为一切都很奇怪,我找不到用来形容它的话.首先,我将向您介绍与问题有关的类的来源.我的实际问题是在页面的最后.大块的代码是以防万一,因为我不知道什么可以解释我的问题.这是一个服务外观,可以从我的flex应用程序中获取调用.
public class ServiceFacade implements IAuthenticationService, IProfileService, ICampaignService {
@Autowired
private IAuthenticationService authenticationService;
@Autowired
private IProfileService profileService;
@Autowired
private ICampaignService campaignService;
public void login(User user) throws AuthenticationException{
authenticationService.login(user);
}
@Override
public void logout() throws AuthenticationException {
authenticationService.logout();
}
@Override
public void sendForgottenPassword(String email) {
authenticationService.sendForgottenPassword(email);
}
@Override
public Profile getProfile(Long userId) {
return profileService.getProfile(userId);
}
@Override
public Profile updateProfile(Profile profile) {
return profileService.updateProfile(profile);
}
@Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileService.getSocialConnectionsTypes(userId);
}
@Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) …Run Code Online (Sandbox Code Playgroud) 我尝试为我的dao层设置一个Junit测试用例.但是,我不希望测试数据实际上持久保存到DB.
所以我认为我应该在事务上进行并在每次测试后回滚.这让我有以下数据源设置:
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
p:driverClass="org.postgresql.Driver"
p:jdbcUrl="jdbc:postgresql://***"
p:user="***"
p:password="***/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource"
p:packagesToScan="***"
p:hibernateProperties-ref="hibernateProps" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:dataSource-ref="dataSource"
p:sessionFactory-ref="sessionFactory"/>
Run Code Online (Sandbox Code Playgroud)
待测试的dao类设置如下:
@Repository
@Transactional
@SuppressWarnings("unchecked")
public class BallotBoxRepositoryHibernateImpl implements BallotBoxRepository {
@Autowired
private SessionFactory sessionFactory;
@Override
public void saveVote(DaoObject v) {
Session sess = sessionFactory.openSession();
sess.beginTransaction();
sess.save(v);
sess.getTransaction().commit();
sess.close();
}
[...]
}
Run Code Online (Sandbox Code Playgroud)
实际的持久工作确实很有效.但是,从未进行过预期的回滚:
INFO main transaction.TransactionalTestExecutionListener:292 - Rolled back transaction after test execution for test context [...]
Run Code Online (Sandbox Code Playgroud)
TransactionalTextExecutionListener定义如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = …Run Code Online (Sandbox Code Playgroud) 鉴于Microsoft已弃用Transactional NTFS(TxF):
Microsoft强烈建议开发人员使用其他方法来满足您的应用程序需求.可以通过更简单和更容易获得的技术来实现TxF开发的许多场景.此外,在未来的Microsoft Windows版本中可能无法使用TxF.
虽然TxF是一组功能强大的API,但自Windows Vista以来,开发人员对此API平台的兴趣非常有限,主要是由于其复杂性和开发人员在应用程序开发过程中需要考虑的各种细微差别.因此,Microsoft正在考虑在未来版本的Windows中弃用TxF API,以便将开发和维护工作集中在对大多数客户更有价值的其他功能和API上.
这意味着我需要一个替代方案:
我的交易要求相当简单 - 移动两个文件:
tx = BeginTransaction();
{
MoveFile(testResults, testResultsArchive); //throws if there's a problem
MoveFile(cdcResponse, cdcResponseArchive); //throws if there's a problem
CommitTransaction(tx);
}
finally
{
CloseHandle(tx);
}
Run Code Online (Sandbox Code Playgroud)
我已经考虑过转向MoveFile到CopyFile+ DeleteFile:
CopyFile(testResults, testResultsArchive); //throws if there's a problem
CopyFile(cdcResponse, cdcResponseArchive); //throws if there's a problem
DeleteFile(testResults);
DeleteFile(cdcResponse);
Run Code Online (Sandbox Code Playgroud)
但我希望有一个好的解决方案,而不是一个错误的解决方案.所以我再试一次:
CopyFile(testResults, testResultsArchive); //throws if there's a problem
CopyFile(cdcResponse, cdcResponseArchive); //throws if there's a problem …Run Code Online (Sandbox Code Playgroud) 我编写Spring + Vaadin应用程序。我想添加QueryDSL来访问数据库(Oracle)。我查看了文档(http://docs.spring.io/spring-data/jdbc/docs/current/reference/html/core.querydsl.html),并阅读了Spring建议使用标准QueryDSL api的内容。我依赖于以下方面来介绍我的项目:
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-sql</artifactId>
<version>${querydsl.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我的beans.xml如下:
<bean id="dataSourceOracle" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.oracle.driverClassName}" />
<property name="url" value="${db.oracle.url}"/>
<property name="username" value="${db.oracle.username}" />
<property name="password" value="${db.oracle.password}" />
<property name="defaultAutoCommit" value="false" />
</bean>
Run Code Online (Sandbox Code Playgroud)
在我的DatabaseFacade实现中,执行以下配置:
private SQLQueryFactory query;
@Autowired
@Qualifier("DataSource")
public void setDataSource(DataSource dataSource) {
Provider<Connection> provider = new SpringConnectionProvider(dataSource);
Configuration configuration = new Configuration(new OracleTemplates());
configuration.setExceptionTranslator(new SpringExceptionTranslator());
query …Run Code Online (Sandbox Code Playgroud) 我正在使用Spring Boot 1.4.2中的spring-boot-starter-data-jpa.
一切正常(@Entity类发现,数据源自动配置,事务自动配置,EntityManager自动配置).
我无法找到交易超时可以设置的位置.由于我希望尽可能深入地使用Spring Boot,因此我不希望在任何Config文件中以编程方式声明事务管理器bean.
" 常见应用程序属性引用 "仅提及JTA事务管理器的超时,但没有为自动配置提供简单JPA使用.请注意,我不是在寻找jdbc查询超时.
有任何想法吗 ?
我试图分析一下我有两个班级的情况.一个类是ProcessImpl,它是起点并在内部调用其他子事务.我不知道什么是错误的.processImpl正在导入一些东西并将相关数据写入数据库.
眼镜
Spring-orm版本:3.2.18.RELEASE.
JDK版本:1.8.
Db:H2(记录任何db相同的性能).
问题
如果我@Transactional从ProcessImpl.processStage()过程中删除需要~50秒
如果我保持@Transactional从ProcessImpl.processStage()过程需要〜15分钟.不知道为什么会这样.我一直试图解决这个问题,但没有运气.请看下面的代码.
要求:
完成processStage()应完成或完全回滚,即使其中一个子事务失败.
Fyi:我也收到很多消息:"参与现有交易".试图通过添加propagation=Propagation.NESTED到processStage()但没有工作来克服这个问题.
ProcessImpl类.
public class ProcessImpl {
/*This is the big transaction that calls other transactional stuff from MyServiceImpl
* This is starting point you can say for the process...
*
* If we remove @Transactional from here the process is lightning fast
* With transactional : 15minutes
* Without transactional …Run Code Online (Sandbox Code Playgroud) 我对Spring的@Transactional如何在内部工作感兴趣,但在我读到它的每个地方都有一个代理概念.代理应该是自动装配代替真正的bean,并使用额外的事务处理方法"装饰"基本方法.这个理论对我来说非常清楚,并且非常有意义,因此我尝试检查它的运作方式.我创建了一个带有基本控制器和服务层的Spring Boot应用程序,并使用@Transactional注释标记了一个方法.服务看起来像这样:
public class TestService implements ITestService {
@PersistenceContext
EntityManager entityManager;
@Transactional
public void doSomething() {
System.out.println("Service...");
entityManager.persist(new TestEntity("XYZ"));
}}
Run Code Online (Sandbox Code Playgroud)
控制器调用服务:
public class TestController {
@Autowired
ITestService testService;
@PostMapping("/doSomething")
public ResponseEntity addHero() {
testService.doSomething();
System.out.println(Proxy.isProxyClass(testService.getClass()));
System.out.println(testService);
return new ResponseEntity(HttpStatus.OK);
}}
Run Code Online (Sandbox Code Playgroud)
整个过程都有效,新实体会持久保存到DB,但我关注的重点是输出:
Service...
false
com.example.demo.TestService@7fb48179
Run Code Online (Sandbox Code Playgroud)
似乎服务类是显式注入而不是代理类.不仅"isProxy"返回false,而且类输出("com.example.demo.TestService@7fb48179")表明它不是代理.
你可以帮帮我吗?为什么不注入代理,如果没有代理,它甚至如何工作?有什么方法可以"强迫"它被代理,如果是这样 - 为什么Spring没有默认注入代理?
没有太多要添加,这是一个非常简单的应用程序.应用程序属性也不花哨:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=superSecretPassword
spring.datasource.url=jdbc:mysql://localhost:3306/heroes?serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=create-drop
Run Code Online (Sandbox Code Playgroud)
先感谢您!
transactional ×10
spring ×5
hibernate ×4
java ×4
jpa ×2
architecture ×1
junit ×1
persist ×1
persistent ×1
postgresql ×1
querydsl ×1
queuing ×1
spring-boot ×1
spring-orm ×1
transactions ×1
txf ×1