I am looking at optimising my application and have found that loading the contained BLOB takes up a lot of resources on the database and application server. After a bit of reading I found that LAZY loading was not supported and required byte code instrumentation. After struggling a little bit with finding instruction on how to use the ant tasks I created a sample application to see the benefits.
Code:
package com.ejb3workshop.standalonejpa.entities;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.apache.log4j.Logger;
@Entity
@Table(name = "Simple")
public class SimpleWith implements Serializable
{
public static Logger logger = Logger.getLogger(SimpleWith.class);
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String description;
private double number;
@Lob
@Basic(fetch=FetchType.LAZY)
private byte[] byteData;
public byte[] getByteData()
{
return byteData;
}
public void setByteData(byte[] byteData)
{
this.byteData = byteData;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public static Logger getLogger()
{
return logger;
}
public static void setLogger(Logger logger)
{
SimpleWith.logger = logger;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public double getNumber()
{
return number;
}
public void setNumber(double number)
{
this.number = number;
}
}
Here is my ant task:
Code:
<taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
</taskdef>
<instrument verbose="true">
<fileset dir="build/classes">
<include name="**/*.class"/>
</fileset>
</instrument>
I can see the byte code instrumentation is being applied after compile time.
Quote:
starting instrumentation
processing class : com.ejb3workshop.standalonejpa.Main; file = /Users/alex/Documents/CourseWare/EJB3 Workshops/Examples/StandAloneJPA/build/classes/com/ejb3workshop/standalonejpa/Main.class
processing class : com.ejb3workshop.standalonejpa.entities.Simple; file = /Users/alex/Documents/CourseWare/EJB3 Workshops/Examples/StandAloneJPA/build/classes/com/ejb3workshop/standalonejpa/entities/Simple.class
processing class : com.ejb3workshop.standalonejpa.entities.SimpleWith; file = /Users/alex/Documents/CourseWare/EJB3 Workshops/Examples/StandAloneJPA/build/classes/com/ejb3workshop/standalonejpa/entities/SimpleWith.class
However when running the following using Hibernate 3.6 I don't see any difference. The BLOB is loaded every time, so it doesn't seem to be working.
Code:
EntityManagerFactory factory = Persistence.createEntityManagerFactory("standaloneJPA");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
Simple found = em.find(Simple.class, 1);
if (found == null)
{
Simple simple = new Simple();
simple.setName("NAME");
em.persist(simple);
}
else
{
found.setNumber(found.getNumber()+1);
}
em.getTransaction().commit();
em.getTransaction().begin();
SimpleWith foundWith = em.find(SimpleWith.class, 1);
if (foundWith == null)
{
Simple simple = new Simple();
simple.setName("NAME");
em.persist(simple);
}
else
{
foundWith.setNumber(foundWith.getNumber()+1);
}
em.getTransaction().commit();
em.close();
any idea what I am doing wrong or what I should expect. Here is my output showing the SQL statements executed
Quote:
run:
Hibernate: select simple0_.id as id0_0_, simple0_.description as descript2_0_0_, simple0_.name as name0_0_, simple0_.number as number0_0_ from Simple simple0_ where simple0_.id=?
Hibernate: update Simple set description=?, name=?, number=? where id=?
Hibernate: select simplewith0_.id as id0_0_, simplewith0_.byteData as byteData0_0_, simplewith0_.description as descript2_0_0_, simplewith0_.name as name0_0_, simplewith0_.number as number0_0_ from Simple simplewith0_ where simplewith0_.id=?
Hibernate: update Simple set byteData=?, description=?, name=?, number=? where id=?