views:

796

answers:

2

Hello

I am using Ejb3 and JPA (based on Hibernate and Oracle 10g at the moment)

I have an entity that contains a clob

@Entity
@Table(name = "My_TAB")
public class ExampleEntity implements java.io.Serializable {

    private Clob someText;

    public void setSomeText(Clob someText) {
        this.someText= someText;
    }

    @Column(name = "COLUMN_NAME")
    public Clob getSomeText() {
        return this.someText;
    }

Then I want to save an entity of this type.

At the moment I am doing the following which works perfectly

ExampleEntity exampleEntity = new ExampleEntity();
exampleEntity.setSomeText(Hibernate.createClob(aStringValue));
someOtherDao.save(exampleEntity);

However this ties my code to Hibernate! I have specifically avoided so far Hibernate extensions and used only JPA annotations. The code works because indeed Hibernate is my current implementation.

Is there some sort of JPA API that allows me to create a clob in a generic way? So if later I decide to switch to Toplink/EclipseLink or something else I won't have to change a thing?

+2  A: 

There's such an example is the JPA spec (§ 9.1.5)

@Column(name="DESC", 
columnDefinition="CLOB NOT NULL", 
table="EMP_DETAIL") 
@Lob 
public String getDescription() { return description; }

I believe it's the standard way for CLOB.

ewernli
You also may want `@Basic(fetch=LAZY)` for lazy loading.
axtavt
@Basic(fetch=LAZY) wont work in a hibernate property. At least not without instumentation.
yannisf
Thanks! Apparently I completely missed the @Lob annotation.
kazanaki
A: 

I'm not sure I would do it again, but in the past when I needed to limit my app to the most widely used subset of sql types, I implemented binary objects using a separate table of char and stored it gzipped and base 64 encoded. Using XML mapping, it was something like:

<list name="encodedValue" lazy="true" table="TABLE" cascade="all-delete-orphan">
  <key column="TABLE_ID"/>
  <index column="SEQ"/>
  <element type="string" column="LINE" length="2000"/>
</list>

In the code, the getValue method retrieved the getEncodedValue results, concatenated them all together and then decoded and unzipped them. As an optimization, I put a simple value column on the parent table and used that if it could fit in the 2000 characters and only went to the child table if necessary.

The setValue method gzipped and encoded it and stored it in the simple column if it fit, otherwise split it into the child records. That also gets you lazy loading and if the data fits in a single column, it doesn't even have to do a separate query.

Probably overkill if you know that your databases will support clobs, but worked pretty well in our situation.

Brian Deterling