@LastModifiedDate会导致数据库中的其他更新



这有点奇怪,但是当在我的实体上使用@LastModifiedDate注释时,它会在保存新对象时触发额外的更新。
如果我设置@EnableJpaAuditing(modifyOnCreate = false(,那么它只是插入,但在保存新实体时没有设置上次修改日期。

有没有办法让它在插入时设置上次修改日期,而不会对数据库进行额外的更新,或者我错过了什么?

这是我的代码:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class JpaConfig {
@Bean
public AuditorAware<String> auditorProvider() {
return () -> System.getProperty("user.name", "undefined");
}
}

带有 getter 的抽象实体(使用 getter,因为我在其他地方将它们用于 Hibernate(:

@MappedSuperclass
public abstract class AbstractGenericJson extends GenericJson {
private DateTime createdDate;
private DateTime lastModifiedDate;
private String createdBy;
private String lastModifiedBy;
@Column(name = "audit_create_ts", nullable = false, updatable = false)
@CreatedDate
@Convert(converter = JodaDateTimeConverter.class)
public DateTime getCreatedDate() {
return createdDate;
}
public void setCreatedDate(DateTime createdDate) {
this.createdDate = createdDate;
}
@Column(name = "audit_update_ts")
@LastModifiedDate
@Convert(converter = JodaDateTimeConverter.class)
public DateTime getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(DateTime lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
@Column(name = "audit_user_tx", updatable = false)
@CreatedBy
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Column(name = "audit_upd_user_tx")
@LastModifiedBy
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
...

实体类

@Entity
@EntityListeners(AuditingEntityListener.class)
public class ConsumerInteraction extends AbstractGenericJson {
private UUID uuid;
@Id
@GeneratedValue
@Column(name = "uuid")
public UUID getId() {
return uuid;
}
...

回购:

@Repository
public interface InteractionRepo extends JpaRepository<ConsumerInteraction, UUID>{}

我的测试:

@SpringBootTest(
properties = {
"spring.jpa.properties.hibernate.jdbc.time_zone=UTC",
"logging.level.org.springframework.data.auditing=DEBUG"
})
@RunWith(SpringRunner.class)
@DataJpaTest
@Import(JpaConfig.class)
public class InteractionRepoTest {
@Autowired
InteractionRepo dao;
@Test
public void testInsertSingle() {
ConsumerInteraction i = new ConsumerInteraction();
i.setCustomId(290050);
i = dao.save(i);
dao.flush();
...

日志显示两个 Touched 事件,一个用于空 uuid,另一个用于生成 uuid 后,据我了解,这是后续更新的原因,因为没有修改其他字段。

2018/05/06 00:36:01 DEBUG | main | o.s.d.a.AuditingHandler:161 - Touched ConsumerInteraction{uuid=null, id=290050} - Last modification at java.util.GregorianCalendar[time=1525563361086,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2018,MONTH=4,WEEK_OF_YEAR=18,WEEK_OF_MONTH=1,DAY_OF_MONTH=6,DAY_OF_YEAR=126,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=36,SECOND=1,MILLISECOND=86,ZONE_OFFSET=0,DST_OFFSET=3600000] by xxx 
2018/05/06 00:36:05 DEBUG | main | o.s.d.a.AuditingHandler:161 - Touched ConsumerInteraction{uuid=4e38645b-aa13-435d-8416-4bb3792a2482, id=290050} - Last modification at java.util.GregorianCalendar[time=1525563365716,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2018,MONTH=4,WEEK_OF_YEAR=18,WEEK_OF_MONTH=1,DAY_OF_MONTH=6,DAY_OF_YEAR=126,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=36,SECOND=5,MILLISECOND=716,ZONE_OFFSET=0,DST_OFFSET=3600000] by xxx 
Hibernate: insert into tInteraction (audit_user_tx, audit_create_ts, audit_upd_user_tx, audit_update_ts, average_value, company_names, consumer, contract_id, id, description, desk, duration, ext_party_id, include_in_vote, interaction_date, interaction_id, interaction_type, interaction_value, override_value, party_name, payer_allocation_name, regions, sectors, sell_side_contacts, status, updated_by, updated_date, user_comment, user_rating, period_id, region, uuid) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: update tInteraction set audit_upd_user_tx=?, audit_update_ts=?, average_value=?, company_names=?, consumer=?, contract_id=?, description=?, desk=?, duration=?, ext_party_id=?, include_in_vote=?, interaction_date=?, interaction_id=?, interaction_type=?, interaction_value=?, override_value=?, party_name=?, payer_allocation_name=?, regions=?, sectors=?, sell_side_contacts=?, status=?, updated_by=?, updated_date=?, user_comment=?, user_rating=? where uuid=?

使用 Spring Boot jpa 1.5.12 和 Hibernate 5.2.16.Final。

抱歉,我的帖子很长,但我即将放弃使用@LastModifiedDate。谢谢!

发现默认时区的问题。显然,最后修改日期似乎是在本地时区设置的,而我使用的是 UTC 进行休眠。 在调试时,我注意到lastModifiedDate总是使我的实体变脏,因为时间戳的时区不匹配。

更新了基类以使用java.util.Date作为时间戳,并从Joda DateTime中删除了转换器,现在问题似乎已解决。

问题可能出在转换器的实现上。这是一个已知的奇怪情况,与Hibernate的肮脏检查有关。查看这篇文章。

最新更新