【问题标题】:Spring boot, jms listener and database transactionSpring boot、jms监听器和数据库事务
【发布时间】:2020-10-28 00:01:25
【问题描述】:

我在数据库中有 2 条记录,因为在其他线程中没有找到本地创建和保存的实体。

我的配置是这样的:

@Configuration
@EnableJms
@EnableJpaRepositories
public class MyConfiguration {

@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(ConnectionFactory connectionFactory,
                                                                  DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    configurer.configure(factory, connectionFactory);
    factory.setRecoveryInterval(5000);
    factory.setSessionTransacted(true);
    return factory;
}

}

还有这个,application.properties:

java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
spring.jms.jndi-name=jms/MyCF
spring.jms.listener.concurrency=5
spring.jms.listener.acknowledge-mode=auto
spring.jms.template.receive-timeout=5000

spring.datasource.jndi-name=jdbc/MyDataSource

spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.generate-ddl=false

我有带有序列生成器的 MyEntity 实体

@Getter
@Setter
@Entity
@Table(name = "MY_ENTITY")
public class MyEntity {
@Id
@Column(name = "ID", nullable = false, precision = 0)
@SequenceGenerator(name="SqName", sequenceName="SQ_ID", allocationSize = 1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SqName")
private long id;
@Basic
@Column(name = "NAME", nullable = true, length = 4000)
private String name;

然后我有我的 JMS 监听器:

@JmsListener(destination="jms/MyQueue")
public void onMessage(Message message) throws Exception {
    myService.save(myRepository.findOneByName("name1"));
}

然后我有一个 MyService 类:

@Service
MyServiceImpl implements MyService {
    save(MyEntity myEntity) {
        if(myEntity == null) myEntity = new MyEntity();
        myEntity.setName("name1");
        // do something
        myRepository.save(myEntity);
    }
}

发生了什么,在一行和一个线程中,新创建的实体被保存在 myRepository(本地,尚未在 DB 中)中,而在另一个线程中的下一行,当它再次调用 save 方法时,它没有找到实体名称为“name1”,所以最后我在数据库中有 2 条记录为“name1”。

myRepository.findOneByName("name1") = null;

那么,我应该在 MyServicImpl 类或 JmsListener 中添加 @Transactional 注释来保存方法吗?

我的意思是,我在 MyServiceImpl 类的 save 方法中有 @Transactional,但它从未发生过,但也许只是巧合。

另外,我应该在配置中添加 JtaTransactionManager 吗?

【问题讨论】:

    标签: spring spring-boot jpa jms jta


    【解决方案1】:

    这是同名实体的并发更改,考虑乐观锁

    【讨论】:

    • 请解释一下你的答案!
    猜你喜欢
    • 1970-01-01
    • 2015-02-28
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 2023-03-26
    相关资源
    最近更新 更多