admin管理员组文章数量:1320661
I'm working with a multitenant Spring Boot app using Spring Data JPA and Hibernate. My entity has auditing fields (@CreatedBy, @CreatedDate, @LastModifiedBy, @LastModifiedDate) populated via @EnableJpaAuditing, and they are correctly saved to the database.
However, after calling save() to merge the entity, the returned entity has the auditing fields set to null, even though they are correctly persisted in the database. When I call entityManager.refresh(object), the fields are correctly populated, but I don’t want to query the database again.
Here is my code:
Models:
@Getter
@Setter
@MappedSuperclass
@RequiredArgsConstructor
@Audited(targetAuditMode = NOT_AUDITED)
@EntityListeners(AuditingEntityListener.class)
public class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column
private UUID id;
@Column(updatable = false)
@CreatedBy
private String createdBy;
@Column(updatable = false)
@CreatedDate
private LocalDateTime createdDate;
@Column
@LastModifiedBy
private String lastModifiedBy;
@Column
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
@Entity
@Getter
@Setter
@Audited
public class SystemConfiguration extends AbstractEntity {
@Enumerated(EnumType.STRING)
private SystemConfigurationTypeEnum code;
@Column
private String description;
@Column
private String value;
@Column(columnDefinition = "boolean default true")
private boolean active = true;
@Version
@NotAudited
private Integer version;
}
Repository:
@Repository
public interface SystemConfigurationRepository extends JpaRepository<SystemConfiguration, UUID> {
Optional<SystemConfiguration> findByCode(SystemConfigurationTypeEnum code);
void deleteByCode(SystemConfigurationTypeEnum code);
boolean existsByCode(SystemConfigurationTypeEnum code);
}
PersistenceConfig:
@Configuration
@EnableJpaRepositories(
basePackages = {"${multitenancy.tenant.repository.packages}"},
entityManagerFactoryRef = "tenantEntityManagerFactory",
transactionManagerRef = "tenantTransactionManager"
)
@EnableConfigurationProperties(JpaProperties.class)
public class TenantPersistenceConfig {
@Autowired
private ConfigurableListableBeanFactory beanFactory;
@Autowired
private JpaProperties jpaProperties;
@Value("${multitenancy.tenant.entityManager.packages}")
private String entityPackages;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean tenantEntityManagerFactory(
@Qualifier("dynamicDataSourceBasedMultiTenantConnectionProvider") MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver") CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName("tenant-persistence-unit");
em.setPackagesToScan(entityPackages);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Map<String, Object> properties = new HashMap<>(this.jpaProperties.getProperties());
properties.put(BEAN_CONTAINER, new SpringBeanContainer(this.beanFactory));
properties.put(MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.physical_naming_strategy", "system_configurations_service.multitenancy.MyPhysicalNamingStrategy");
em.setJpaPropertyMap(properties);
return em;
}
@Bean
@Primary
public JpaTransactionManager tenantTransactionManager(
@Qualifier("tenantEntityManagerFactory") EntityManagerFactory emf) {
JpaTransactionManager tenantTransactionManager = new JpaTransactionManager();
tenantTransactionManager.setEntityManagerFactory(emf);
return tenantTransactionManager;
}
Service method:
@Override
public SystemConfigurationDTO update(SystemConfigurationTypeEnum code, SystemConfigurationDTO systemConfigurationDTO) throws Exception {
log.debug("Request to update System Configuration by code: {}", code);
repository.findByCode(code).orElseThrow(() -> new GenericException(SERVICE_TYPE_NOT_FOUND, code));
SystemConfiguration systemConfiguration = repository.save(mapper.toEntity(systemConfigurationDTO));
return mapper.toDTO(systemConfiguration);
}
Mapper(Impl are setting all the fields):
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface SystemConfigurationMapper {
SystemConfiguration toEntity(SystemConfigurationDTO dto);
SystemConfiguration toEntity(SystemConfigurationPatchDTO dto);
SystemConfigurationDTO toDTO(SystemConfiguration entity);
List<SystemConfigurationDTO> toDTO(List<SystemConfiguration> entityList);
}
Currently Output:
{
"id": "fdc59f03-27c7-436d-8022-8e28786639d0",
"createdBy": null,
"createdDate": null,
"lastModifiedBy": null,
"lastModifiedDate": null,
"code": "data",
"description": "data",
"value": "data",
"active": true,
"version": 4
}
Expected Output:
{
"id": "fdc59f03-27c7-436d-8022-8e28786639d0",
"createdBy": "system",
"createdDate": "2025-01-16 09:36:39",
"lastModifiedBy": "anonymousUser",
"lastModifiedDate": "2025-01-17 15:12:45",
"code": "data",
"description": "data",
"value": "data",
"active": true,
"version": 4
}
Ensured @EnableJpaAuditing is configured. Used saveAndFlush(), which populates @LastModifiedBy and @LastModifiedDate, but @CreatedBy and @CreatedDate are still null. The auditing fields are being persisted correctly but aren’t returned in the entity after save(). I want to avoid calling entityManager.refresh() and get all auditing fields populated without an additional database query. How can I achieve this?
本文标签:
版权声明:本文标题:java - Auditing fields return null after updating entity(save()) in multitenant Spring Data JPA app - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742063693a2418703.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论