I have a standard Spring Framework (v3.1.2) java (v1.6) database backed (postgres v9.1) web application, which runs on Apache Tomcat (v6.0). Please note that I am using Hibernate 3.6.10.Final and Spring Data JPA 1.2.0.RELEASE.
I have two database entity classes - Chapter and ChapterText - with a one-to-one relationship between them...
@Entity @Table(name="chapter")
public class Chapter implements Comparator<Chapter> {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CHAPTER_SEQ")
@SequenceGenerator(name="CHAPTER_SEQ", sequenceName="chapter_seq", allocationSize=1)
@Column(name="id")
private Long id;
@OneToOne(cascade=CascadeType.ALL, optional=false, fetch=FetchType.LAZY, orphanRemoval=true) @PrimaryKeyJoinColumn
private ChapterText chapterText;
// other properties plus setters and getters
}
@Entity @Table(name="chapterText")
public class ChapterText {
@Id
@GeneratedValue(generator="foreign")
@GenericGenerator(name="foreign", strategy="foreign", parameters={ @Parameter(name="property", value="parent") })
@Column(name="id")
private Long id;
@OneToOne(mappedBy="chapterText", optional=false)
private Chapter parent;
@Column(name="body") @Lob
private String body;
// setters and getters
}
Now, as ChapterText contains a @Lob property, which can potentially hold a large amount of text, i've marked the chapterText property in the Chapter class such that it will be lazily loaded.
I have the OpenEntityManagerInViewFilter setup and configured, so I can add a Chapter entity to the model (with the name "chapter"), then in my JSPX file I should be able to do this...
${chapter.chapterText.body}
This should lazily-load the ChapterText entity and include the value of the body property in the XHTML page generated for the calling browser.
This is an entrely standard way of displaying information from a database, which i've been using for years. However, this is the first time i've had to use a @Lob property with Postgres. When I do this, i'm presented with the following stack trace...
org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.servlet.ServletException: javax.servlet.jsp.JspException: javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
org.hibernate.exception.GenericJDBCException: could not load an entity: [project.vo.db.ChapterText#1]
.
.
.
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
From what i've been able to find out, Posgres requires accessing Large Objects to be accessed via a transaction with auto-commit set to false.
Annoyingly, the only approach i've been able to think of to get around this is to create a repository method which fetches the @Lob property, mark it with @Transactional and load the value into a bean specifically created for display purposes. While that does work, it seems a little inelegant.
Does anyone have any ideas for an alternative approach?