Lob returns null using play framework and Ebean and H2

866 views Asked by At

I am developing a program with play 2.3(with Ebean and H2) for java. I have a model like this:

@Entity
public class DeviceModel extends Model implements PathBindable<DeviceModel> {

@Id
public Long id;


@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] picture;

...

In my controller I have a function which writes a picture as byte[] inside a DeviceModel object and calls the update() function. so now the picture should be saved in database.

And i have this function to show the picture:

public static Result picture(Long id) {
    final DeviceModel deviceModel = DeviceModel.findByID(id);
    if (deviceModel == null){
        return notFound();
    }
    return ok(deviceModel.picture);
}

the funny thing is that deviceModel.picture is null!

but in my view, I have this:

        @if(deviceModel.picture != null) {
                show the picture!
        } else{
            do something else
        }

but here, deviceModel.picture is not null!!! and MOST OF THE TIMES the picture will be shown correctly!!

I deleted the @Basic(fetch=FetchType.LAZY) but it didn't solve the problem.

any Idea why is it like this?

2

There are 2 answers

0
behzad On BEST ANSWER

I found a work around for this issue, but I still like to know the reason, why accessing the picture field directly, returns null.

here is the work around: I just made my picture field private, and made getter and setter my self. now in my Controller, with getPicture() I always get the data

@Entity
public class DeviceModel extends Model implements PathBindable<DeviceModel> {

@Id
public Long id;


@Lob
@Basic(fetch=FetchType.LAZY)
private byte[] picture;


public byte[] getPicture() {
    return picture;
}

public void setPicture(byte[] picture) {
    this.picture = picture;
}

...
1
Ridcully On

The reason for that behavior is the FetchType.LAZY (which apparently is also the default for Lobs). It tells Ebean to fetch the data lazily, i.e. not immediately when you load the object, but only when you actually access it.

As Ebean cannot detect the access when you go directly at the field (picture), the loading doesn't happen at all and you get null.

By using getPicture(), the code of which is enhanced by Ebean, it knows to load the data before returning the value.

You can overcome that behavior by simply using FetchType.EAGER. But you should only do that, if you're sure you need the data always, because it takes more time and memory (e.g. in your example, if you have 100s of pictures and you only want to show a list of names, it would not be necessary to load all the pictures' actual image data as well.