0 Replies Latest reply on Jul 25, 2013 1:35 PM by Sunil Padda

    Envers is not respecting lazy one-to-one mapping

    Sunil Padda Newbie



      I have two entities, Place and PlaceShape. PlaceShape is marked as a lazy one-to-one association and its working perfectly fine in Hibernate. However, when I edit Place (without loading PlaceShape) and commit the changes, Envers seems to loading PlaceShape to compute differences. It's not loading any one-to-many collections though. This is causing performance related issues, as PlaceShape is a huge entity and requires loading in specific circumstances. Call stacktrace, SQL log and Java code are mentioned below. Any help or suggestions are greatly appreciated.






      Here is the stack-trace where the shape is getting fetched:


      at sun.reflect.GeneratedMethodAccessor361.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:172)
      at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:175)
      at org.hibernate.envers.entities.mapper.MultiPropertyMapper.mapToMapFromEntity(MultiPropertyMapper.java:107)
      at org.hibernate.envers.synchronization.work.CollectionChangeWorkUnit.generateData(CollectionChangeWorkUnit.java:56)
      at org.hibernate.envers.synchronization.work.AbstractAuditWorkUnit.perform(AbstractAuditWorkUnit.java:72)
      at org.hibernate.envers.synchronization.AuditProcess.executeInSession(AuditProcess.java:114)
      at org.hibernate.envers.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:152)
      at org.hibernate.engine.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:543)
      at org.hibernate.engine.ActionQueue.beforeTransactionCompletion(ActionQueue.java:216)
      at org.hibernate.impl.SessionImpl.beforeTransactionCompletion(SessionImpl.java:571)
      at org.hibernate.jdbc.JDBCContext.beforeTransactionCompletion(JDBCContext.java:250)
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:138)
      at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)


      Here is the SQL log for the operation described above:


      select place0_.PID as PID1_10_6_, place0_.NAME as NAM2_10_6_ from PLACE place0_ where place0_.PID=?;
      update PLACE (NAME) values (?);
      select hibernate_sequence.nextval from dual;
      select placeshape0_.SPATIAL_ID as SPATIAL1_19_7_, placeshape0_.PID as PID3_19_7_, placeshape0_.SHAPE as SHAPE19_7_, place1_.PID as PID1_10_0_, place1_.NAME as NAM2_10_0_ from PLACE_SHAPE placeshape0_ left outer join PLACE place1_ on placeshape0_.PID=place1_.PID where placeshape0_.PID=?;
      insert into Revinfo (log, revtstmp, username, rev) values (?, ?, ?, ?);
      insert into PLACE_AUD (REVTYPE, NAME, PID, REV) values (?, ?, ?, ?);

      Here is the code for the entities:


      @Table(name = "PLACE")
      public class Place implements FieldHandled {
          private long pid;
          private String name; 
          private PlaceShape placeShape;
          private FieldHandler fieldHandler;
          @Column(name = "PID", columnDefinition = "NUMBER(10,0)", nullable = false)
          public long getPid() {
              return pid;
          public void setPid(long pid) {
              this.pid = pid; 
          @Column(name = "NAME", columnDefinition = "NVARCHAR(100)", nullable = true)
           public String getName() {
               return name;
          public void setName(String name) {
               this.name = name;
          @OneToOne(mappedBy = "place", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, optional = true)
          @LazyToOne(value = LazyToOneOption.NO_PROXY)
          public PlaceShape getPlaceShape() {
              if (fieldHandler != null) {
                  return (PlaceShape) fieldHandler.readObject(this, "placeShape", placeShape);
              return placeShape;
          public void setPlaceShape(PlaceShape placeShape) {
              if (fieldHandler != null) {
                  this.placeShape = (PlaceShape) fieldHandler.writeObject(this, "placeShape", this.placeShape, placeShape);
              this.placeShape = placeShape;
      @Table(name = "PLACE_SHAPE")
      public class PlaceShape implements Serializable {
          private long id;
          private Place place;
          private Geometry shape;
          @SequenceGenerator(name = "SEQ_STORE", sequenceName = "SPATIAL_SEQ", allocationSize = 1)
          @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STORE")
          @Column(name = "SPATIAL_ID", columnDefinition = "NUMBER(10, 0)", nullable = false)
          public long getId() {
              return id;
          public void setId(long id) {
              this.id = id;
          @OneToOne(fetch = FetchType.EAGER)
          @JoinColumn(name = "PID", referencedColumnName = "PID")
          public Place getPlace() {
              return place;
          public void setPlace(Place place) {
              this.place = place;
          @Type(type = "org.hibernatespatial.GeometryUserType")
          @Column(name = "SHAPE", columnDefinition = "MDSYS.SDO_GEOMETRY", nullable = false)
          public Geometry getShape() {
              return shape;
          public void setShape(Geometry shape) {
              this.shape = shape;