Hibernate

Using MySQL Collations in Java

I’ve recently discovered Stackoverflow as a nice pass-time on the one hand and as a valuable source for answers on the other hand. Normally it takes only a few minutes to get answers for most questions. However, I managed to ask a question that nobody was able to answer yet. The question was about Collations. As I’m suspecting that Collations are a Java feature that is hardly used, I kept working on the problem myself rather then just waiting for an answer on Stackoverflow.

I’ve managed to get something working right now. It’s not completely tested but it should work quite well. What I’m doing is the following: I parse the charset files of MySQL (on an Ubuntu system, you can find them in /usr/share/mysql/charsets/) and do the collation based on those files myself rather than using Java’s built-in collations.

EDIT: I’ve just created a github project that’s available as a Maven artifact from Sonatype’s OSS repository.


Detaching and Attaching Persistent Objects on Serialization

Today I’ve received a mail by someone interested in a serialization mechanism I described some days ago. This mechanism was implemented to avoid dealing with detached Hibernate objects in different HTTP (i.e. Wicket) requests (it’s not restricted to Hibernate though). The idea is quite simple: detach objects if they are persistent, serialize them if they are transient, deserialize and attach for the next request – all transparently. So far, this isn’t very special and doesn’t justify such a complicated approach. However, it’s the only way of attaching and detaching object graphs that consist of transient and persistent objects I know.
Read the rest of this entry »


A Custom reuseable LoadableDetachableModel for Spring/Hibernate

the annoyance


org.hibernate.LazyInitializationException - could not initialize proxy - the owning Session was closed
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed

the problem

Generally, detached objects in Hibernate are a bad thing when it comes to reusing objects between web-requests. Detached objects are objects that have been persistent but are not attached to a Hibernate session. They’re easily produced but can be a mess if it comes to Lazy-Loading or updating them. Just consider the following case


Foo foo = _myDAO.getFoo(); // attached object

add(new Link("fooLink", new Model(foo)) {

  protected void onClick() {
    Foo foo = (Foo) getModelObject(); // now it's detached as this is called in the next request
    Bar bar = foo.getBar(); // possible lazy-loading exception if bar gets loaded lazily

  }
}

the solution

First be sure to use the OpenSessionInViewFilter sothat a new hibernate session is opened when the request gets attached and closed when it gets detached.

Then the solution of course is a to use a LoadableDetachableModel that gets a fresh instance from the persistence-layer on each request. Could look like that:


IModel fooModel = new LoadableDetachableModel() {

  protected Object load() {
    return _myDAO.getFoo();
  }
}

add(new Link("fooLink", fooModel) {

  protected void onClick() {
    Foo foo = (Foo) getModelObject(); // attached as LDM has loaded a fresh instance
    Bar bar = foo.getBar(); // no lazy loading exception as still attached

  }
}

the improvement

LoadableDetachableModels are a nice thing but it’s quite a lot of work to inject your DAO (or service) and then create a new LDM for each of your objects in each and every one of your panels. so we came up with a more generic version of the LoadableDetachableModel. First, let your model-objects implement an Interface, say IPersistentObject with the single method


  Serializable getId();

As your object are likely to have a primary key named id it’ll be no problem anyway. Then create the following class:


public class PersistentObjectModel extends LoadableDetachableModel {

  private static final long serialVersionUID = 1L;

  private final Class _clazz;

  private final Serializable _id;

  @SpringBean(name = "myDao")
  private IMyDao _myDao;

  @SuppressWarnings("unchecked")
  public PersistentObjectModel(final T object) {
    super(object);

// object may be a hibernate proxy, so get the actual class
    if (object instanceof HibernateProxy) {
      _clazz = (Class) ((HibernateProxy) object).getHibernateLazyInitializer()
.getImplementation().getClass();
    } else {
      _clazz = (Class) object.getClass();
    }
    _id = object.getId();
    // inject the bean
    InjectorHolder.getInjector().inject(this);
  }

  public PersistentObjectModel(final Class clazz, final Serializable id) {
    clazz = clazz;
    _id = id;
    // inject the bean
    InjectorHolder.getInjector().inject(this);
  }

  @Override
  protected T load() {
    // the DAO then simply passes the params to hibernate (or spring's hibernatetemplate
    return _myDao.getById(_clazz, _id);
  }

  @SuppressWarnings("unchecked")
  @Override
  public T getObject() {
    return (T) super.getObject();
  }

}

This makes working with hibernate objects really easy. There are two options:

  1. Use the object e.g.

    setModel(new PersistentObjectModel(foo));

  2. Use only class and id.

    This might happen e.g. if you pass your id using PageParameters (but better encrypt it ;-) )
    setModel(new PersistentObjectModel(Foo.class, 1));

Hope that saved you some time writing boilerplate code ;-) have fun


Hibernate: could not read column value from result set?

I got this Error today after changing the primary key of my model objects from int to Serializable (as I wanted all of my objects, even the ones with a String primary key to use the same API, which was limited to int). But when I started the app I got the Error and the following Exception:

org.hibernate.type.SerializationException: could not deserialize
at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:217)
at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:240)
at org.hibernate.type.SerializableType.fromBytes(SerializableType.java:82)
at org.hibernate.type.SerializableType.get(SerializableType.java:39)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)
…..

I even got this one as cause:

Caused by: java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2279)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2748)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)
at java.io.ObjectInputStream.(ObjectInputStream.java:280)
….

EOF? wtf? Don’t get too confused with that EOF, the solution was simply to add the type of the id in the mapping file.

Before:

<id name=”id”>
<generator class=”native”>
</id>

After:

<id name=”id” type=”integer”> <!– or long or string of whatever your hibernate type is –>
<generator class=”native”>
</id>


Using Wicket’s jmx-panel to view Hibernate’s Statistics

The Java Management Extensions (JMX) is perfect to build manageable applications without the need to create any administration frontend. Managed Beans (MBeans) are similar to regular Java Beans. Hibernate offers an MBean-wrapper around its Statistics API which is really interesting to optimize caching. Therefore, I was looking for a simple way to use JMX with Wicket. Fortunately, Wicket can also be managed with JMX. All it needs is to drop the wicket-jmx JAR on the classpath – no configuration needed! It is therefore sufficient to add wicket-jmx to the POM:


<dependency>
 <groupid>org.apache.wicket</groupid>
 <artifactid>wicket-jmx</artifactid>
 <version>1.3.0-SNAPSHOT</version>
</dependency>

But Wicket (more precisely Wicketstuff) also contains a simple JMX client called wicketstuff-jmx-panel. Using this client is as simple as adding a single component to whatever Wicket-page:

POM:

<repository>
 <id>wicket-stuff-repository</id>
 <name>Wicket-Stuff Repository</name>
 <url>http://www.wicketstuff.org/maven/repository</url>
</repository>
<!-- SNIP -->
<dependency>
 <groupid>org.wicketstuff</groupid>
 <artifactid>wicketstuff-jmx-panel</artifactid>
 <version>1.3.0-SNAPSHOT</version>
</dependency>

Java:


add(new JmxPanel("jmx"));

However, documentation on this JMX panel is sparse. It took me some time to figure out the following: This panel filters all MBeans that do not have the Wicket-application’s name in their domain. This behaviour may be changed using an annonymous inner class:


add(new JmxPanel("jmx") {
 protected IDomainFilter getDomainFilter() {
   return DOMAIN_FILTER;
}
});

private static final IDomainFilter DOMAIN_FILTER = new IDomainFilter() {
 private static final long serialVersionUID = 1L;

 public boolean accept(String domain) {
   // your filter code
   return true;
}
};

It does make sense to filter out some MBeans as there are already some by default, e.g. for java.util.logging which you probably don’t use at all.

Now it’s time to add Hibernate’s statistics MBean. This MBean is can be used per SessionFactory. I therefore decided to do registration and unregistration together with SessionFactory creation. As I am also using Spring, I went for my own SessionFactoryBean:


public class MBeanRegisteringLocalSessionFactoryBean extends
   org.springframework.orm.hibernate3.LocalSessionFactoryBean {

 private String _sessionFactoryName;
 private ObjectName _objectName;
 private MBeanServer _mbeanServer;

 @Override
 protected void afterSessionFactoryCreation() throws Exception {
   super.afterSessionFactoryCreation();
   try {
     // register JMX MBean
     _objectName = new ObjectName("Hibernate:type=statistics,application="
       + getSessionFactoryName());
     _mbeanServer = getMBeanServer();

     final StatisticsService mBean = new StatisticsService();
     mBean.setSessionFactory(getSessionFactory());
     _mbeanServer.registerMBean(mBean, _objectName);

   } catch (final Throwable t) {
     log.warn("failed to register MBean for SessionFactory: " + _objectName, t);
     _objectName = null;
     _mbeanServer = null;
   }
   // if _objectName != null --> MBean was registered
 }

 @Override
 protected void beforeSessionFactoryDestruction() {
   if (_objectName != null) {
     try {
       _mbeanServer.unregisterMBean(_objectName);
     } catch (final Throwable t) {
       log.warn("failed to unregister MBean for SessionFactory: "
         + _objectName.getDomain());
     }
   }
 }

 /* SNIP: getMBeanServer(), getSessionFactoryName(), setSessionFactoryName(String) */
}

I copied (sorry, there is no nicer way yet) the code for getMBeanServer() from wicket-jmx’s Initializer class (sorry, can’t find an online version – you can get the source using Maven) in order to get the exact same behaviour. Now you only need to replace LocalSessionFactoryBean with MBeanRegisteringLocalSessionFactoryBean in your beans.xml and you are set. In order to enable statistics by default, add these two lines to your hibernate properties:


hibernate.generate_statistics=true
hibernate.cache.use_structured_entries=true

That’s it! Hibernate statistics directly from your webapp: