5

I have tried with List and Map, but I cannot figure out how to force Hibernate 3.6.4 to persist null values in those collections. This is what I've tried:

@ElementCollection(fetch=FetchType.EAGER)
@Column(columnDefinition="longtext")
private Map<Integer, String> parameterValues;

and

@ElementCollection(fetch=FetchType.EAGER)
@OrderColumn
@Lob @Column(length=65535)
private List<String> parameterValues;

If the Map or List contains a null value, Hibernate does not persist it in a row in the collection table. When the collection is retrieved from the database, it has fewer elements than when it was stored because those that are null are not restored. The List restored null values for indices between the first and last indices with non-null values, but any null values at the end of the list were left out. The Map only contained entries for non-null values.

I hope this is making sense. It seems like a bug in Hibernate to me, but I'm hoping it's something I can fix with a different configuration.

1
  • 1
    I would use the null object pattern instead of trying to store null. Find a special String meaning "no value", and store it into the list or map. Commented Mar 6, 2013 at 21:01

2 Answers 2

6

Turns out this is a bug in Hibernate...well, not according to Gavin King, but according to many others that would like to store Nulls in the DB. See HHH-772. This issue will apparently never be resolved.

So, I had to work around it by adding an @Embeddable class for my parameter values that happily stores a null value in the DB, like this:

@Embeddable
@Access(AccessType.FIELD)
public final class ParameterValue {
    @Basic(optional=false)
    private int id;

    @Column(columnDefinition="longtext")
    private String value;

    /** For JPA */
    ParameterValue() {} 

    public ParameterValue(int id, String value) {
            this.id = id;
        this.value = value;
    }

    /**
     * @return the id
     */
    public int getId() {
            return id;
    }

    /**
     * @return the value
     */
    public String getValue() {
            return value;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Could it be possible to use this workaround with a List<Product>, for example? Basically your ParameterValue class would have to include a Product variable in it. Another thing, this workaround will slightly change the API of the holding class, right? For each value in my list I would need to call getValue(), if I understand correctly. It would be great to somehow delegate methods to the value. It's sad that the Hibernate team is sometimes very stubborn. It isn't the first bug I find in Hibernate that doesn't get solved despite the high number of community requests. Thanks for this!
Hard to believe Hibernate has such a basic hole as this. But there it is.
0

I seem to have the same problem, but:

  1. happens on Oracle 11g but not on MySQL and not on HSQL
  2. For me also blank values seem to be the problem automatically turning into null values when inserted into the table
  3. The rows are there with value null and the collection loaded by Hibernate is empty (effectively empty since the map would only have the one entry) (tried Hibernate 3.6.8, 3.6.10 and 4.1.10)
  4. What then happens is that when I update the Map, Hibernate wants to update the collection (where Hibernate thinks its empty) while the same entry already exists in the database, resulting in a ORA-00001 Unique Constraint Violation

I wonder what the magic is that inserting a blank becomes null in the table. Inserting pseudo values for blank and null seem tedious. And I point out again that I only have the problem under Oracle. The same software runs fine under MySQL and HSQL.

3 Comments

oracle treats an empty string as null. It's one of its well known... "feature".
So i would conclude that using Oracle exposes some kind of bug in Hibernate Collection Loader for primitives? (e.g. Map<String,String>).
It is a bug...but one that will not be fixed: link

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.