6

I have the following 2 classes (trimmed down for this post)

public class ApplicationVO implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -3314933694797958587L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;


    @OneToOne(fetch = FetchType.LAZY, mappedBy = "application")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    private ApplicationHomeScreenVO applicationHomeScreen;

...
...
... 
}


public class ApplicationHomeScreenVO implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -9158898930601867545L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @JsonProperty("id")
    private Integer id;

    @OneToOne(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.SAVE_UPDATE })
    @JoinColumn(name="application_id")
    @JsonProperty("application")
    protected ApplicationVO application;    

    ...
    ...
    ...
}

I am trying to load an applicationById wuthout loading the applicationHomeScreen Unfortunately the lazy loading doesnt seem to be working. I have looked at other posts and they recommend setting the option=false flag on the @OneToOne annotation but unfortunately, applicationHomeScreen can be optional

I am now trying to use projections but that is not working either for me either

When I call the following method

 public ApplicationVO findApplicationById(Integer applicationId) {

        Criteria criteria = currentSession().createCriteria(ApplicationVO.class);
        criteria.add(Restrictions.eq("id", applicationId));

        criteria.setProjection(Projections.projectionList()
                .add(Projections.property("applicationHomeScreen"), "applicationHomeScreen"))
              .setResultTransformer(Transformers.aliasToBean(ApplicationVO.class));

        ApplicationVO applicationVO = (ApplicationVO) criteria.uniqueResult();

        return applicationVO;
    }

I get the stack trace

java.lang.ArrayIndexOutOfBoundsException: 0
    at org.hibernate.loader.criteria.CriteriaLoader.getResultRow(CriteriaLoader.java:168)
    at org.hibernate.loader.criteria.CriteriaLoader.getResultColumnOrRow(CriteriaLoader.java:148)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:754)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:953)
    at org.hibernate.loader.Loader.doQuery(Loader.java:921)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)
    at org.hibernate.loader.Loader.doList(Loader.java:2554)
    at org.hibernate.loader.Loader.doList(Loader.java:2540)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370)
    at org.hibernate.loader.Loader.list(Loader.java:2365)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1682)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
    at org.hibernate.internal.CriteriaImpl.uniqueResult(CriteriaImpl.java:402)
    at com.dao.database.impl.ApplicationDAOImpl.findApplicationById(ApplicationDAOImpl.java:349)

Can anyone recommend an approach I can use to either a) get lazy loading working properly for one to one mappings where the association is not required b) get projections working so I dont need to load any child associations if they are not needed

Thank you Damien

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
Damien Gallagher
  • 981
  • 4
  • 13
  • 25

2 Answers2

2

The only option is to follow these steps:

  1. Add @LazyToOne to the one-to-one association:

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "application")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    @LazyToOne(value = LazyToOneOption.NO_PROXY)
    private ApplicationHomeScreenVO applicationHomeScreen;
    
  2. Configure bytecode enhancement

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
1

Optional @OneToOne relationships cannot be lazy because the non-owning side of the relationship does not now whether the child exists(optional) - Hibernate doesn't know whether to put a proxy object or null. There are several workarounds for this. This link has detailed explanation on some workarounds

isah
  • 5,221
  • 3
  • 26
  • 36
  • I saw these options already cheers- some of them are not appealing. Should i be able to limit the results with projections? – Damien Gallagher Apr 21 '15 at 12:01
  • You can use result transforming as you tried and select only custom columns from db and then return this custom bean, but that's another thing(you'll not be working with actual entity - it is suitable for some cases) – isah Apr 21 '15 at 12:08
  • yeah i know what you mean. That didnt work for me unfortunately with my mapping - would you know why? – Damien Gallagher Apr 21 '15 at 12:10