|
|
|
We get the following error message when persisting/updating/deleting associations: {code} Caused by: org.hibernate.PropertyNotFoundException: Could not locate getter method for property [co.fingerprintsoft.spring.hibernate.audit.Customer#null] at org.hibernate.internal.util.ReflectHelper.findGetterMethod(ReflectHelper.java:400) at org.hibernate.property.access.internal.PropertyAccessBasicImpl.<init>(PropertyAccessBasicImpl.java:41) at org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl.buildPropertyAccess(PropertyAccessStrategyBasicImpl.java:27) at org.hibernate.envers.internal.tools.ReflectionTools.getGetter(ReflectionTools.java:53) at org.hibernate.envers.internal.tools.ReflectionTools.getGetter(ReflectionTools.java:46) at org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper.mapToMapFromEntity(MultiPropertyMapper.java:105) at org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit.generateData(CollectionChangeWorkUnit.java:48) at org.hibernate.envers.internal.synchronization.work.AbstractAuditWorkUnit.perform(AbstractAuditWorkUnit.java:62) at org.hibernate.envers.internal.synchronization.AuditProcess.executeInSession(AuditProcess.java:106) at org.hibernate.envers.internal.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:153) at org.hibernate.envers.internal.synchronization.AuditProcessManager$1.doBeforeTransactionCompletion(AuditProcessManager.java:46) at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:706) at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:373) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2271) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:230) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61){code} We have tracked down the error to: {code} @Override public boolean mapToMapFromEntity( SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) { boolean ret = false; for ( PropertyData propertyData : properties.keySet() ) { Getter getter; if ( newObj != null ) { getter = ReflectionTools.getGetter( newObj.getClass(), propertyData, session.getFactory().getServiceRegistry() ); } else if ( oldObj != null ) { getter = ReflectionTools.getGetter( oldObj.getClass(), propertyData, session.getFactory().getServiceRegistry() ); } else { return false; }
ret |= properties.get( propertyData ).mapToMapFromEntity( session, data, newObj == null ? null : getter.get( newObj ), oldObj == null ? null : getter.get( oldObj ) ); }
return ret; } {code} Specifically the line: {code} getter = ReflectionTools.getGetter( newObj.getClass(), propertyData, session.getFactory().getServiceRegistry() ); //Line 105: org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper } {code} To replicate the error: h5. Customer.java {code:java} import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.validation.constraints.Size;
import org.hibernate.annotations.NaturalId; import org.hibernate.envers.Audited; import org.hibernate.validator.constraints.Length;
import com.sun.istack.internal.NotNull;
@Entity @Audited public class Customer implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NaturalId @NotNull @Length(min = 6, max = 6) private String customerNumber;
@Audited @OneToMany(mappedBy = "customer") private Collection<Account> accounts = new ArrayList();
@Size(max = 10, message = "{Size.customer.devices}") @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) private Set<Device> devices = new HashSet();
public String getCustomerNumber() { return customerNumber; }
public void setCustomerNumber(String customerNumber) { this.customerNumber = customerNumber; }
public Collection<Account> getAccounts() { return accounts; }
public void setAccounts(Collection<Account> accounts) { this.accounts = accounts; }
public Set<Device> getDevices() { return devices; }
public void setDevices(Set<Device> devices) { this.devices = devices; } } {code} h5. Account.java {code:java} import javax.persistence.Entity; import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.validation.constraints.NotNull;
import org.hibernate.envers.Audited;
@Entity @Audited public class Account {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Audited @ManyToOne @JoinColumn( name = "customer_customernumber", referencedColumnName = "customerNumber", columnDefinition = "VARCHAR(6)", foreignKey = @ForeignKey(name = "fk_acc_cust_custnumber")
) @NotNull private Customer customer;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Customer getCustomer() { return customer; }
public void setCustomer(Customer customer) { this.customer = customer; } } {code} h5. Device.java {code:java} import javax.persistence.Entity; import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne;
import org.hibernate.envers.Audited;
@Entity @Audited public class Device {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Audited @ManyToOne @JoinColumn(name = "customer_id", foreignKey = @ForeignKey(name = "fk_dev_cust_id") ) private Customer customer;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Customer getCustomer() { return customer; }
public void setCustomer(Customer customer) { this.customer = customer; } } {code} h5. Scenario {code:java} Customer customer = new Customer(); customer.setCustomerNumber("123457"); entityManager.getTransaction().begin(); entityManager.persist(customer); entityManager.getTransaction().commit();
Device device = new Device(); device.setCustomer(customer);
Account account = new Account(); account.setCustomer(customer); entityManager.getTransaction().begin(); entityManager.persist(account); entityManager.getTransaction().commit(); entityManager.getTransaction().begin(); entityManager.remove(account); entityManager.getTransaction().commit(); {code} The problem stems from the fact that the property is not correctly identified in the PropertyData field: {code} propertyData = {PropertyData@6977} name = {String@6983} "_co_fingerprintsoft_spring_hibernate_audit_Account_customer" beanName = null accessType = {String@6984} "property" store = {ModificationStore@6908} "FULL" usingModifiedFlag = false modifiedFlagName = {String@6985} "customerNumber_MOD" {code}
|
|
|
|