1

I have an entity called ReferenceForm which contains an AutoPopulatingList of ReferenceItems. It looks like this:

@Entity
public class ReferenceForm implements Serializable{

    private static final long serialVersionUID = -5633788166190438576L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    long id;


    @lob
    private AutoPopulatingList<ReferenceItem> referenceItems;

}

If I add no annotation at all to the AutoPopulatingList, the field type which hibernate creates is varbinary(255). This causes string truncation errors. To work around this, I used the @lob annotation. This felt questionable at the time, but it worked fine. At this point I was just using HSQLDB.

Now the application needs to run against MSSQL. I have generated the schema using Hibernate, and referenceItems ia an image column on the ReferenceForm table. The items themselves are stored in the ReferenceItem table.

Is @lob an appropriate annotation here?.

EDIT: ReferenceItem looks like this:

@Entity
public class ReferenceItem implements Serializable {

private static final long serialVersionUID = -9077063073733429102L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
long id;

private Title title;
private String firstName;
private String surname;
private String positionHeld;
private String institutionCompany;

@Embedded
private Address address;
@Embedded
private Telephone telephone;

private String email;
private boolean existingReference;

private String fileName;

public ReferenceItem() {
}

...getters and setters
}

SECOND EDIT:

Thanks to Willome for suggesting using @OneToMany. In the end, this is what worked.

//from

@lob
private AutoPopulatingList<ReferenceItem> referenceItems;
//to
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
  • @OneToMany accurately describes the nature of the relationship
  • Use the interface (List) instead of the implementation when defining the field. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html
  • Define the CascadeType, otherwise this error appears on saving the entity: org.hibernate.TransientObjectException: object references an unsaved transient instance
  • Make the FetchType EAGER otherwise you cannot load the form in a different transaction: this error appears: failed to lazily initialize a collection of role: ReferenceForm.referenceItems, could not initialize proxy - no Session
Mark Chorley
  • 2,087
  • 2
  • 22
  • 29

2 Answers2

1

You should replace your @Lob annonation with a @OneToMany and replace the AutoPopulatingList with a collection-valued field declared as an interface type (Check out the topic 6.1. Persistent collections on this link http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html.)

//@Lob
@OneToMany(mappedBy = "referenceForm")
private AutoPopulatingList<ReferenceItem> referenceItems; //fail AutoPopulatingList is not an interface 

@OneToMany(mappedBy = "referenceForm")
private Set<ReferenceItem> referenceItems; // OK with Set/Collection/List
willome
  • 3,062
  • 19
  • 32
  • Thanks for your response. If I use that annotation on an AutoPopulatingList I see this error: "org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @ OneToMany, @ ManyToMany or @ CollectionOfElements:" – Mark Chorley Jul 09 '13 at 17:25
  • I am going to try defining the field as a List and see what happens then – Mark Chorley Jul 09 '13 at 17:26
  • OK I thought that AutoPopulatingList was extending a Collection. please update your question with the AutoPopulatingList entity then. – willome Jul 09 '13 at 18:27
  • It does, it implements List. This is the AutoPopulatingList: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/util/AutoPopulatingList.html. It is curious that the code which interprets the @OneToMany annotation apparently cannot recognise this. – Mark Chorley Jul 10 '13 at 09:32
  • Just discovered this post: http://stackoverflow.com/questions/8169196/illegal-attempt-to-map-a-non-collection-as-a-onetomany-manytomany-or-collec which indicates that I must declare the mapped field as an interface (in this case List). I have tried this with the OneToMany annotation and am able to initialise the ApplicationContext and create the database OK. However I now have an error on saving. I think I will edit the question with the details. – Mark Chorley Jul 10 '13 at 09:47
  • EDIT : Mark you are right I saw that too and I updated the answer – willome Jul 10 '13 at 09:48
  • You should close your question and ask a new one if you have got some trouble while saving your entity ;) – willome Jul 10 '13 at 09:51
  • I was thinking that but the trouble stems from the use of @ OneToMany with an AutoPopulatingList. I have the full answer now and will post it below. – Mark Chorley Jul 10 '13 at 10:03
0

Thanks to Willome for suggesting using @OneToMany. In the end, this is what worked.

//from

@lob
private AutoPopulatingList<ReferenceItem> referenceItems;

//to

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<ReferenceItem> referenceItems = new AutoPopulatingList<ReferenceItem>(ReferenceItem.class);
  • @OneToMany accurately describes the nature of the relationship

  • Use the interface (List) instead of the implementation when defining the field. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html

  • Define the CascadeType, otherwise this error appears on saving the entity: org.hibernate.TransientObjectException: object references an unsaved transient instance

  • Make the FetchType EAGER otherwise you cannot load the form in a different transaction: this error appears: failed to lazily initialize a collection of role: ReferenceForm.referenceItems, could not initialize proxy - no Session

Mark Chorley
  • 2,087
  • 2
  • 22
  • 29