I have two Spring Boot applications working with the same database. The main app is uses the database fully, the other app is meant for reporting (basically read data created by the main app).
The main app uses envers (org.hibernate:hibernate-envers:5.3.1.Final), it creates audit tables to track changes (tables are created by liquibase). I need to read historical data by the reporting app, so I added envers to that app as well. Below are some snippets from the reporting app.
Entity example:
@Entity
@Table(name = "applications")
@Audited
@AuditOverride(forClass = BaseEntity.class)
@EqualsAndHashCode(callSuper = true)
@Getter
public class ApplicationEntity extends BaseEntity {
@ManyToOne(optional = false)
@JoinColumn(name = "client_id")
private ClientEntity client;
private BigDecimal amount;
}
Superclass:
@MappedSuperclass
@EntityListeners({PreventModificationsListener.class})
@ToString(of = "id")
@EqualsAndHashCode(of = "id")
@Getter
public abstract class BaseEntity {
@VisibleForTesting
@Setter(PACKAGE)
@Id
private Long id;
@Version
private Long version;
}
Configuration:
spring:
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQL95Dialect
id:
new_generator_mappings: true
defaultSchema: public
order_updates: true
jdbc:
fetch_size: 0
hbm2ddl:
auto: validate
show_sql: false
format_sql: false
enable_lazy_load_no_trans: true
org.hibernate:
envers:
audit_table_prefix: audit_
audit_table_suffix:
As a result reporting app fails during starts on schema validation:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [rev] in table [audit_xyz]; found [int8 (Types#BIGINT)], but expecting [int4 (Types#INTEGER)]
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateColumnType(AbstractSchemaValidator.java:159)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:143)
at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:191)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
... 136 common frames omitted
Any help and suggestions are highly appreciated.
One of my colleagues have pointed out on difference between two applications that turned out the be the missing link.
Revision entity class:
@Entity
@Table(name = "audit_revisions")
@SequenceGenerator(name = "seq_gen", sequenceName = "audit_revisions_seq", allocationSize = 1)
@RevisionEntity
@EntityListeners(AuditingEntityListener.class)
@Getter
public class AuditRevision {
@Id
@GeneratedValue(generator = "seq_gen", strategy = SEQUENCE)
@RevisionNumber
private Long id;
@RevisionTimestamp
private Date revisionDate;
@CreatedBy
private String createdBy;
}