开发者

Hibernate - Avoiding LazyInitializationException - Detach Object From Proxy and Session

开发者 https://www.devze.com 2023-01-11 19:09 出处:网络
MyObject myObject = repositoryHibernateImpl.getMyObjectFromDatabase(); //transaction is finished, and no, there is not an option to reopen it
MyObject myObject = repositoryHibernateImpl.getMyObjectFromDatabase();
//transaction is finished, and no, there is not an option to reopen it
ThirdPartyUtility.doStuffWithMyObjectType( myObject );

at this point you've already defined what is lazy and eager loaded, and the third party utility will try to call all of the methods on your "myObject" instance, this is fine because you don't want to return anything for the lazily loaded properties, unfortunately it doesn't return null, it throws a LazyInitializationException.

This ha开发者_运维技巧ppens because you're actually calling the method on Hibernate's proxy of your object, and it knows that it hasn't fetched that data, and throws an exception.

Is it even possible to get the underlying object with null values so that a getter just returns null, and doesn't throw an exception? Basically detaching the object so that Hibernate is no longer aware of it at all. The accessor to the object that is lazily loaded must return null, it cannot return the actual values, we want to be able to convert the entity into a POJO without having to create an object that looks just like the entity and has to remap all the values.


Let's say you have a field, in the getter you could:

MyField getMyField() {
    if (Hibernate.isInitialized(myField)) {
        return myField;
    }
    return null;
}

From the javadoc of org.hibernate.Hibernate:

public static boolean isInitialized(Object proxy): check if the proxy or persistent collection is initialized.


If you don't want to couple your domain to Hibernate, another possibility is to have your DAO instantiate your own instance of the entity from inside getMyObjectFromDatabase() and populate that with the appropriate fields from Hibernate's proxy. I've done this and it works well.

Obviously this is more code, but you're guaranteed a "pure" instance of your entity (complete with null uninitialized values) if that's what you want.


check my solution.

Minimal example:

I do not load the property from the object but from the controller.
Code:

{..}

MyProp prop = employeeController.getMyProp(employee);

{..}

This initiaqlizes the property via repository object and returns it.
EmployeeController.java:

public Set<MyProp> getMyProp(Employee employee) {

    if (this.employeeRepository.InitMyProp(employee)){

        return employee.getMyProp();
    }

    return null;
}

Repository get/open the session, reload employee object ! and initialize lazy loaded field
EmployeeRepository.java:

public boolean InitMyProp(Employee employee) {

    if (Hibernate.isInitialized(employee.getMyProp())){
        return true;
    }

    try {
        Session session = getSession();

        session.refresh(employee);

        Hibernate.initialize(employee.getMyProp());

    } catch (Exception ex) {
        return false;
    }

    return true;
}

private Session getSession(){

    if (session == null || !session.isConnected() || !session.isOpen()){
        session = HibernateUtil.getSessionFactory().getCurrentSession();
    }
    if (!session.getTransaction().isActive()) {
        session.beginTransaction();
    }
    return session;
}

I have in my solution a TableView with several thousand records and 2 further TableViews with details on the selected record in the first TableView.
hope it helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消