我在与工作相关的问题上遇到了一些问题:
业务需要通过组播主动接收数据报包(在这种情况下意味着我们正在使用while(true)循环)。
伪代码如下所示:
while (true) {
receivePacket();
parsePacket();
saveParsedPacketToDatabase();
}
我们正在使用Spring Data JPA将实体保存到数据库 - 这是制作插入的组件:
@Service
@Transactional
public class InsertService {
@Inject
private DataRepository dataRepository;
@Transactional(propagation = Propagation.NEVER)
public void saveParsedPacketToDatabase(List<Data> data) {
dataRepository.save(data);
dataRepository.flush();
}
}
数据对象包含日期字段,让我们说在 @ PrePersist / Update 上设置insertTime:
@PreUpdate
@PrePersist
void preSave() {
insertTime = DateTime.now(DateTimeZone.UTC).toDate();
}
现在问题是我们得到2个相同的对象(所有字段都是相同的但 insertTime和生成的id。重要的是 - insertTime差异是毫秒,不超过100 )为每个插入的实体。
我一直在尝试调试这个问题并找到问题所在,但我不知道..我们肯定没有通过多播获取重复数据,我认为插入技术可能有问题。跳过无限循环不是一个选择 - 可能需要以某种方式排队......
我非常感谢任何帮助,
干杯, 马尔钦
答案 0 :(得分:0)
今年早些时候,我遇到了类似的问题。首先摆脱整个preSave()
方法。 @PreUpdate
和@PrePersist
是垃圾,而不是(应该)由Hibernate 4支持,会让您比您想象的更令人头疼。我知道这是因为这是我尝试解决这个问题时的原始路线。
我将假设您正在使用MySQL数据库或类似数据库,但任何体面的RDBMS都应该能够处理我提出的建议。
要解决此问题,您要执行的操作是使用insertTime
为@Generated(value = GenerationTime.ALWAYS)
字段添加注释。这基本上对你的数据库说“无论何时插入这个记录,都要为这个字段生成一个值”。
在数据库中,为表示insertTime
的列指定一个默认值,该列是当前时间。大多数RDBMS支持这样的事情,我对这样一个字段的HSQL表声明是dateModified TIMESTAMP DEFAULT NOW
,但您可能需要根据您使用的数据库类型进行检查。每当您将insertTime值插入数据库时,都应该设置它。作为预防措施,如果我的@Generated
字段有值,我只是将它们设置为空以确保没有任何内容,并且任何出来的值必须由数据库设置。
如果这不起作用或您需要更多解释,请告诉我。
答案 1 :(得分:0)
我已经玩了一段时间了,我意识到(通过调试hibernate插件)我没有说出重要部分:我一直在使用Spring&#39; s ApplicationEventPublisher 接口,用于发布业务事件。
整个事情介于 receivePacket()和 parsePacket()方法之间。
我意识到ApplicationEventPublisher的 publishEvent 方法是使数据库插入 - 我不确定它为什么要这样做 - 我和猜测春天的数据代码中某处有什么东西在听 - 当我有更多的时间时,我会尝试本地化来源 - 现在我是很高兴我得到了它。
很抱歉没有提供相关信息;我希望将来会有人利用这些信息。
最佳, 马尔钦