【发布时间】:2019-11-16 00:28:13
【问题描述】:
我正在尝试将使用 Hibernate Envers 的审计支持添加到存储实体关系的表中。
我正在使用 Spring Boot 2.1.5 和 Hibernate 5.3.10。
以下是我的课程:
审计实体
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.envers.Audited;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
@Getter
@Setter
@Audited
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditEntity {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(
name = "uuid",
strategy = "org.hibernate.id.UUIDGenerator",
parameters = {
@Parameter(
name = "uuid_gen_strategy_class",
value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
)
}
)
private String id;
@Column(name = "created_date", updatable = false, nullable = false)
@CreatedDate
private long createdDate;
@Column(name = "modified_date")
@LastModifiedDate
private long modifiedDate;
@Column(name = "created_by")
@CreatedBy
private String createdBy;
@Column(name = "modified_by")
@LastModifiedBy
private String modifiedBy;
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof AuditEntity)) {
return false;
}
AuditEntity r = (AuditEntity) o;
return this.getId().equals(r.getId());
}
}
角色
import lombok.Getter;
import lombok.Setter;
import org.hibernate.envers.Audited;
import org.hibernate.envers.NotAudited;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Getter
@Setter
@Audited
@Entity
@Table(name = "role")
public class Role extends AuditEntity {
@Column(name = "name")
private String name;
@NotAudited
private String dontAudit;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.role")
private Set<UserRole> userRoles = new HashSet<>(0);
}
用户
import lombok.Getter;
import lombok.Setter;
import org.hibernate.envers.Audited;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
@Getter
@Setter
@Audited
@Entity
@Table(name = "user")
public class User extends AuditEntity {
private String sso;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user")
private Set<UserRole> userRoles = new HashSet<>(0);
}
用户角色
import lombok.Getter;
import lombok.Setter;
import org.hibernate.envers.Audited;
import javax.persistence.*;
@Getter
@Setter
@Audited
@Entity
@Table(name = "user_roles")
@AssociationOverrides({
@AssociationOverride(name = "pk.user", joinColumns = @JoinColumn(name = "USER_ID")),
@AssociationOverride(name = "pk.role", joinColumns = @JoinColumn(name = "ROLE_ID"))
})
public class UserRole extends AuditEntity {
@EmbeddedId
private UserRoleId pk = new UserRoleId();
public User getUser() {
return getPk().getUser();
}
public void setUser(User user) {
getPk().setUser(user);
}
public Role getRole() {
return getPk().getRole();
}
public void setRole(Role role) {
getPk().setRole(role);
}
}
用户角色标识
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;
import java.io.Serializable;
@Getter
@Setter
@Embeddable
@EqualsAndHashCode
public class UserRoleId implements Serializable {
@ManyToOne
private User user;
@ManyToOne
private Role role;
}
当我运行应用程序时,它会抛出以下错误。但是当我不从 AuditEntity 扩展 UserRole 时,应用程序启动成功,但 user_role 表上没有审计列。
错误
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Type not supported: org.hibernate.type.ComponentType
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at com.ercancelik.hibernate.envers.DemoApplication.main(DemoApplication.java:11) [classes/:na]
Caused by: org.hibernate.MappingException: Type not supported: org.hibernate.type.ComponentType
at org.hibernate.envers.configuration.internal.metadata.IdMetadataGenerator.addIdProperties(IdMetadataGenerator.java:120) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.configuration.internal.metadata.IdMetadataGenerator.addId(IdMetadataGenerator.java:200) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.configuration.internal.metadata.AuditMetadataGenerator.generateFirstPass(AuditMetadataGenerator.java:642) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.configuration.internal.EntitiesConfigurator.configure(EntitiesConfigurator.java:95) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.boot.internal.EnversServiceImpl.doInitialize(EnversServiceImpl.java:154) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.boot.internal.EnversServiceImpl.initialize(EnversServiceImpl.java:118) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl.produceAdditionalMappings(AdditionalJaxbMappingProducerImpl.java:101) ~[hibernate-envers-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:297) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
... 16 common frames omitted
【问题讨论】:
-
@C. Weber,我使用的是较新版本的 Hibernate,您提供的链接中提到的错误已在旧版本中解决。此外,我正在尝试将审计支持添加到存储关系的表中。如果我从 UserRole 类中删除“扩展 AuditEntity”部分,应用程序将成功启动,但 user_roles 表不包含 AuditEntity 列。
-
我链接这个问题主要是因为提到了复合 id 并且它们会导致 envers 出现问题。据我所知,您的 UserRole 有一个 EmbeddedId 可能是您问题的根源?
标签: java hibernate spring-boot jpa hibernate-envers