帐户实体
@Getter
@Accessors(chain = true, fluent = true)
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
@ToString(of = {"customerName"}, callSuper = true)
@Entity
@Table(name = "ACCOUNTS",
uniqueConstraints = @UniqueConstraint(name = UNQ_CUSTOMER_NAME, columnNames = { "CUSTOMER_NAME" }),
indexes = {
@Index(name = IDX_CUSTOMER_ENTITY, columnList = "CUSTOMER_ENTITY")
}
)
public class Account extends BaseAutoAssignableVersionableEntity<String, Long> implements Diffable<Account> {
public static final String CUSTOMER_ENTITY = "Customer Entity";
public static final String CUSTOMER_REPORTING_MANAGER = "Customer Reporting Manager";
public static final String CUSTOMER_NAME = "Customer Name";
public static final String ACCOUNT_MANAGER = "Account Manager";
public static final String CITY = "City";
public static final String CUSTOMER_TIME_TRACKING = "Customer Time Tracking";
@NotNull
@Column(name = "CUSTOMER_NAME", nullable = false, length = 150)
@Audited(withModifiedFlag = true)
private String customerName; // Unique
@NotNull
@Size(min = 1, max = 4)
@Column(name = "CUSTOMER_GROUP", nullable = false, length = 4)
@Audited(withModifiedFlag = true)
private String customerGroup;
// @NotNull
@Column(name = "CUSTOMER_ENTITY", nullable = true, length = 150)
@Audited(withModifiedFlag = true)
private String customerEntity; // customer entity is optional and can be same for multiple accounts
@NotNull
@Column(name = "CUSTOMER_REPORTING_MANAGER", nullable = false, length = 150)
@Audited(withModifiedFlag = true)
private String customerReportingManager;
@Column(name = "CUSTOMER_TIME_TRACKING", length = 1)
@Audited(withModifiedFlag = true)
private boolean customerTimeTracking = false;
@NotNull
@OneToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "ACCOUNT_MANAGER_CODE", unique = false, nullable = false, foreignKey = @ForeignKey(name = FK_ACCOUNTS_MGR_RESOURCE_CODE))
@Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "ACCOUNT_MANAGER_CODE_MOD")
private Resource accountManager;
资源实体
@Getter
@Accessors(chain = true, fluent = true)
@NoArgsConstructor
@ToString(of = { "name" }, callSuper = true)
@Entity
// @formatter:off
@Table(name = "RESOURCES",
uniqueConstraints = {
@UniqueConstraint(name = UNQ_RESOURCES_LOGIN_ID, columnNames = {"LOGIN_ID"}),
@UniqueConstraint(name = UNQ_RESOURCES_EMAIL_ID, columnNames = {"EMAIL_ID"}),
@UniqueConstraint(name = UNQ_RESOURCES_PAYROLL_ID, columnNames = {"PAYROLL_ID"})
},
indexes = {
@Index(name = IDX_RESOURCES_NAME, columnList = "NAME")
}
)
// @formatter:on
public class Resource extends BaseAutoAssignableVersionableEntity<String, Long> implements Diffable<Resource> {
public static final String EMAIL_ID = "Email ID";
public static final String GRAYT_HR_ID = "Grayt HR ID";
public static final String NAME = "Name";
public static final String GENEDER = "Gender";
public static final String DESIGNATION = "Designation";
public static final String TYPE_OF_RESOURCE = "Resource Type";
public static final String STATUS_OF_RESOURCE = "Resource Status";
public static final String BASE_LOCATION = "Base Location";
public static final String DEPUTED_LOCATION = "Deputed Location";
public static final String PRIMARY_SKILLS = "Primary Skills";
public static final String SECONDARY_SKILLS = "Secondary Skills";
public static final String EXPECTED_JOINING_DATE = "Expected Joining Date";
public static final String ACTUAL_JOINING_DATE = "Actual Joining Date";
public static final String EXIST_DATE = "Exist Date";
// @Pattern(regexp = REGEX_LOGIN_ID, message = MESSAGE_LOGIN_ID_INVALID)
// @NotNull(message = MESSAGE_LOGIN_ID_MANDATORY)
@Column(name = "LOGIN_ID", nullable = false, length = 100)
private String loginId;
@Email(message = MESSAGE_EMAIL_INVALID)
@Column(name = "EMAIL_ID", nullable = true, length = 255)
@Audited(withModifiedFlag = true)
private String emailId;
@Pattern(regexp = REGEX_PAYROLL_ID, message = MESSAGE_PAYROLL_ID_INVALID)
@Column(name = "PAYROLL_ID", nullable = true, length = 100)
@Audited(withModifiedFlag = true, modifiedColumnName = "PAYROLL_ID_MOD")
private String payrollId;
@NotNull
@Column(name = "NAME", nullable = false, length = 255)
@Audited(withModifiedFlag = true)
private String name;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "GENDER", nullable = false, length = 10)
@Audited(withModifiedFlag = true)
private Gender gender;
@NotNull
@OneToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "DESIGNATION_ID", unique = false, nullable = false, foreignKey = @ForeignKey(name = FK_RESOURCES_DESIGNATION_ID))
@Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "DESIGNATION_ID_MOD")
private Designation designation;
@NotNull
@OneToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "EMP_TYPE_CODE", unique = false, nullable = false, foreignKey = @ForeignKey(name = FK_RESOURCES_EMP_TYPE_CODE))
@Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "EMP_TYPE_CODE_MOD")
private EmploymentType employmentType;
public boolean isFTE() {
return (this.employmentType.equals(EmploymentType.fullTimeEmployee()));
}
@Audited(withModifiedFlag = true, modifiedColumnName = "EMP_STATUS_ID_MOD")
@OneToOne(optional = false, cascade = CascadeType.PERSIST, orphanRemoval = true)
@JoinColumn(name = "emp_status_id", unique = false, foreignKey = @ForeignKey(name = FK_RESOURCES_EMP_STATUS_ID))
private EmploymentStatus employmentStatus;
创建帐户时,请使用现有资源作为帐户管理员并成功创建。然后成功获取历史记录。但是很遗憾,删除了resource_aud表中的资源记录,然后获取了历史记录。它抛出错误以下
javax.persistence.EntityNotFoundException: Unable to find com.gspann.itrack.domain.model.staff.Resource with id IN10000
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:159)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:244)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:166)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
at com.gspann.itrack.domain.model.staff.Resource_$$_jvst4e_12.name(Resource_$$_jvst4e_12.java)
at com.gspann.itrack.domain.model.business.Account.diff(Account.java:328)
at com.gspann.itrack.domain.model.business.Account.diff(Account.java:1)
at com.gspann.itrack.domain.model.common.audit.util.AuditQueryUtils.getAllRevisionById(AuditQueryUtils.java:66)
at com.gspann.itrack.domain.service.impl.AccountManagementServiceImpl.getAllRevisionByAccountCode(AccountManagementServiceImpl.java:268)
下面是由休眠envers生成的查询
/* select
e__,
r
from
com.gspann.itrack.domain.model.business.Account_AUD e__,
com.gspann.itrack.audit.domain.CustomRevisionEntity r
where
e__.REVTYPE <> :_p0
and e__.originalId.code = :_p1
and e__.originalId.REV.id = r.id
order by
e__.originalId.REV.id asc */ select
account_au0_.code as code1_1_0_,
account_au0_.rev as rev2_1_0_,
customrevi1_.id as id1_49_1_,
account_au0_.revtype as revtype3_1_0_,
account_au0_.customer_entity as customer4_1_0_,
account_au0_.customer_entity_mod as customer5_1_0_,
account_au0_.customer_group as customer6_1_0_,
account_au0_.customer_group_mod as customer7_1_0_,
account_au0_.customer_name as customer8_1_0_,
account_au0_.customer_name_mod as customer9_1_0_,
account_au0_.customer_reporting_manager as custome10_1_0_,
account_au0_.customer_reporting_manager_mod as custome11_1_0_,
account_au0_.customer_time_tracking as custome12_1_0_,
account_au0_.customer_time_tracking_mod as custome13_1_0_,
account_au0_.account_manager_code as account14_1_0_,
account_au0_.account_manager_code_mod as account15_1_0_,
account_au0_.country_code as country16_1_0_,
account_au0_.country_code_mod as country17_1_0_,
customrevi1_.last_modified_on as last_mod2_49_1_,
customrevi1_.modified_by as modified3_49_1_,
customrevi1_.timestamp as timestam4_49_1_
from
accounts_aud account_au0_ cross
join
revinfo customrevi1_
where
account_au0_.revtype<>?
and account_au0_.code=?
and account_au0_.rev=customrevi1_.id
order by
account_au0_.rev asc
调用资源的getter方法后,它会生成另一个与资源相关的查询,如下所示
/* select
e__
from
com.gspann.itrack.domain.model.staff.Resource_AUD e__
where
e__.originalId.REV.id = (
select
max(e2__.originalId.REV.id)
from
com.gspann.itrack.domain.model.staff.Resource_AUD e2__
where
e2__.originalId.REV.id <= :revision
and e__.originalId.code = e2__.originalId.code
)
and e__.REVTYPE <> :_p0
and e__.originalId.code = :_p1 */ select
resource_a0_.code as code1_48_,
resource_a0_.rev as rev2_48_,
resource_a0_.revtype as revtype3_48_,
resource_a0_.actual_joining_date as actual_j4_48_,
resource_a0_.actual_joining_date_mod as actual_j5_48_,
resource_a0_.email_id as email_id6_48_,
resource_a0_.email_id_mod as email_id7_48_,
resource_a0_.exit_date as exit_dat8_48_,
resource_a0_.exit_date_mod as exit_dat9_48_,
resource_a0_.gender as gender10_48_,
resource_a0_.gender_mod as gender_11_48_,
resource_a0_.name as name12_48_,
resource_a0_.name_mod as name_mo13_48_,
resource_a0_.payroll_id as payroll14_48_,
resource_a0_.payroll_id_mod as payroll15_48_,
resource_a0_.utilization as utiliza16_48_,
resource_a0_.utilization_mod as utiliza17_48_,
resource_a0_.utilization_type as utiliza18_48_,
resource_a0_.utilization_type_mod as utiliza19_48_,
resource_a0_.base_loc_id as base_lo20_48_,
resource_a0_.base_loc_id_mod as base_lo21_48_,
resource_a0_.deputed_loc_id as deputed22_48_,
resource_a0_.deputed_loc_id_mod as deputed23_48_,
resource_a0_.designation_id as designa24_48_,
resource_a0_.designation_id_mod as designa25_48_,
resource_a0_.emp_status_id as emp_sta26_48_,
resource_a0_.emp_status_id_mod as emp_sta27_48_,
resource_a0_.emp_type_code as emp_typ28_48_,
resource_a0_.emp_type_code_mod as emp_typ29_48_,
resource_a0_.image_id as image_i30_48_,
resource_a0_.image_id_mod as image_i31_48_
from
resources_aud resource_a0_
where
resource_a0_.rev=(
select
max(resource_a1_.rev)
from
resources_aud resource_a1_
where
resource_a1_.rev<=?
and resource_a0_.code=resource_a1_.code
)
and resource_a0_.revtype<>?
and resource_a0_.code=?
下面是获取修订的代码
AuditReader auditReader = this.getAuditReader();
return auditReader.createQuery().forRevisionsOfEntity(clazz, selectedEntitiesOnly, selectDeletedEntities);
我的问题是,为什么它引用审计表而不是主表?
预先感谢