Hibernate Lazy Loading无效

时间:2023-01-15 22:42:13
// This is what I have in my Model Class...

    public class Quotation {
    @JoinColumn(name = "party_id", referencedColumnName = "id")
    @ManyToOne (fetch = FetchType.LAZY)
    private Party party;
    }

And in my Controller I am loading the Quotation object like this:

在我的控制器中,我正在加载Quotation对象,如下所示:

// Load Quotation object by the Entity Manager:- em.find(Quotation.class, quoteId)

    quotation = quotationService.getQuoteHeadById(quoteId);
    log.debug( " party ID --> "+ quotation.getParty.getId() );

But I am not getting even the Party ID of the Party table/object in this Lazy Loading. But if I change the fetch type to Eager, then the log.debug() gives me the ID perfectly.

但是我在这个延迟加载中甚至没有得到Party表/对象的Party ID。但是如果我将fetch类型更改为Eager,那么log.debug()会完美地为我提供ID。

Am I wrong at anything???

我什么都错了???

5 个解决方案

#1


0  

For getting LAZY fields, you need to be inside a transaction. Your controller method seems not transnational. Get an idea from: Understanding transaction session with lazy loading in Spring JPA Hibernate

要获取LAZY字段,您需要进入事务。你的控制器方法似乎不是跨国的。从以下方面获取一个想法:在Spring JPA Hibernate中了解延迟加载的事务会话

#2


0  

use this:

Hibernate.initialize(quotation.getParty());

#3


0  

First of all set transactional at service level. Then configure the hibernate properties like

首先在服务级别设置事务。然后配置hibernate属性

<prop key="hibernate.enable_lazy_load_no_trans">true</prop>

I don't know your configuration, but I hope it will work. (Note: Remember it may be unsafe)

我不知道你的配置,但我希望它能工作。 (注意:记住它可能不安全)

#4


0  

To get party object from quotation object, you have to use left join fetch on your query. Then you will be able to access your party object from quotation object .

要从引用对象获取party对象,必须在查询中使用left join fetch。然后,您将能够从引用对象访问您的派对对象。

Write a jpql query like this:

写一个像这样的jpql查询:

SELECT q from Quotation q left join fetch q.party p 

Then you will not get "could not initialize proxy - no Session" error . By the way, it is a very common error. It means you are trying to access a object which you did not fetch by your query. Hope this answer help.

然后你不会得到“无法初始化代理 - 没有会话”错误。顺便说一句,这是一个非常常见的错误。这意味着您正在尝试访问您的查询未提取的对象。希望这个答案有所帮助

#5


0  

But I am not getting even the Party ID of the Party table/object in this Lazy Loading.

但是我在这个延迟加载中甚至没有得到Party表/对象的Party ID。

Below is the behavior with @ManyToOne (fetch = FetchType.LAZY). Note that the behavior is different when we use hibernate annotations on field vs getters.

以下是@ManyToOne的行为(fetch = FetchType.LAZY)。请注意,当我们在字段vs getter上使用hibernate注释时,行为会有所不同。

In your entity classes you are using hibernate annotations on the field. With this if you call even the getId() method as in quotation.getParty.getId() on the entity it results in initializing the proxy (of party object) and hits the database to fetch it. So the transaction has to be active if not it will result in throwing lazyinitializationexception.

在您的实体类中,您正在使用该字段上的hibernate注释。如果您在实体上调用quot.getParty.getId()中的getId()方法,则会导致初始化代理(派对对象)并命中数据库以获取它。所以事务必须是活动的,否则会导致抛出lazyinitializationexception。

If the intent is only to get the Id of the entity you can place the hibernate annotations on the getter methods. This doesn't initialize the proxy (of party object) to return the id and so doesn't need an active transaction. But accessing any other property other than id will need active transaction and will result in hitting the database.

如果意图只是获取实体的Id,则可以将hibernate注释放在getter方法上。这不会初始化代理(派对对象)以返回id,因此不需要活动事务。但访问除id之外的任何其他属性将需要活动事务并将导致命中数据库。

Have a look at related bug at HHH-3718

看看HHH-3718的相关错误

So, in your party entity use property/getter AccessType instead of field access. As an example instead of

因此,在您的聚会实体中使用property / getter AccessType而不是字段访问。作为一个例子而不是

@Id
@GeneratedValue(...)
private long id;

place them on the getters

把它们放在吸气剂上

@Id
@GeneratedValue(...)
public long getId() { ... }

Make sure you make similar changes to the other fields of the Party entity. You can later explore another option of using @Access(AccessType.PROPERTY/FIELD) instead to get the same effect.

确保对Party实体的其他字段进行类似的更改。您可以稍后探索使用@Access(AccessType.PROPERTY/FIELD)的另一个选项,以获得相同的效果。

Moving on to the EAGER

继续前往EAGER

But if I change the fetch type to Eager, then the log.debug() gives me the ID perfectly.

但是如果我将fetch类型更改为Eager,那么log.debug()会完美地为我提供ID。

This is because the FetchType.EAGER results in fetching the party entity eagerly (no proxy) up front and so we are able to get the id and other properties of party entity. Note that, this results in either a JOIN/extra SELECT query based on configuration.

这是因为FetchType.EAGER导致预先获取派对实体(无代理),因此我们能够获得派对实体的id和其他属性。请注意,这会导致基于配置的JOIN / extra SELECT查询。

Am I wrong at anything???

我什么都错了???

I don't see anything wrong here and it is all because the field vs getter access type have different behavior. So if you are using filed level access, the Hibernate would initialize the proxy even for getting the id of an associated object as per the bug HHH-3718 or until it gets resolved.

我没有看到任何错误,这是因为字段vs getter访问类型具有不同的行为。因此,如果您正在使用文件级别访问,Hibernate将初始化代理,即使是根据错误HHH-3718获取关联对象的ID或直到它得到解决。

And a related topic on hibernate forum regarding field vs property access type that might be of interest Field Vs Property access

关于字段与属性访问类型的hibernate论坛上的相关主题可能是Field Vs Property访问的关注点

Hope this answers your query.

希望这能回答您的疑问。

#1


0  

For getting LAZY fields, you need to be inside a transaction. Your controller method seems not transnational. Get an idea from: Understanding transaction session with lazy loading in Spring JPA Hibernate

要获取LAZY字段,您需要进入事务。你的控制器方法似乎不是跨国的。从以下方面获取一个想法:在Spring JPA Hibernate中了解延迟加载的事务会话

#2


0  

use this:

Hibernate.initialize(quotation.getParty());

#3


0  

First of all set transactional at service level. Then configure the hibernate properties like

首先在服务级别设置事务。然后配置hibernate属性

<prop key="hibernate.enable_lazy_load_no_trans">true</prop>

I don't know your configuration, but I hope it will work. (Note: Remember it may be unsafe)

我不知道你的配置,但我希望它能工作。 (注意:记住它可能不安全)

#4


0  

To get party object from quotation object, you have to use left join fetch on your query. Then you will be able to access your party object from quotation object .

要从引用对象获取party对象,必须在查询中使用left join fetch。然后,您将能够从引用对象访问您的派对对象。

Write a jpql query like this:

写一个像这样的jpql查询:

SELECT q from Quotation q left join fetch q.party p 

Then you will not get "could not initialize proxy - no Session" error . By the way, it is a very common error. It means you are trying to access a object which you did not fetch by your query. Hope this answer help.

然后你不会得到“无法初始化代理 - 没有会话”错误。顺便说一句,这是一个非常常见的错误。这意味着您正在尝试访问您的查询未提取的对象。希望这个答案有所帮助

#5


0  

But I am not getting even the Party ID of the Party table/object in this Lazy Loading.

但是我在这个延迟加载中甚至没有得到Party表/对象的Party ID。

Below is the behavior with @ManyToOne (fetch = FetchType.LAZY). Note that the behavior is different when we use hibernate annotations on field vs getters.

以下是@ManyToOne的行为(fetch = FetchType.LAZY)。请注意,当我们在字段vs getter上使用hibernate注释时,行为会有所不同。

In your entity classes you are using hibernate annotations on the field. With this if you call even the getId() method as in quotation.getParty.getId() on the entity it results in initializing the proxy (of party object) and hits the database to fetch it. So the transaction has to be active if not it will result in throwing lazyinitializationexception.

在您的实体类中,您正在使用该字段上的hibernate注释。如果您在实体上调用quot.getParty.getId()中的getId()方法,则会导致初始化代理(派对对象)并命中数据库以获取它。所以事务必须是活动的,否则会导致抛出lazyinitializationexception。

If the intent is only to get the Id of the entity you can place the hibernate annotations on the getter methods. This doesn't initialize the proxy (of party object) to return the id and so doesn't need an active transaction. But accessing any other property other than id will need active transaction and will result in hitting the database.

如果意图只是获取实体的Id,则可以将hibernate注释放在getter方法上。这不会初始化代理(派对对象)以返回id,因此不需要活动事务。但访问除id之外的任何其他属性将需要活动事务并将导致命中数据库。

Have a look at related bug at HHH-3718

看看HHH-3718的相关错误

So, in your party entity use property/getter AccessType instead of field access. As an example instead of

因此,在您的聚会实体中使用property / getter AccessType而不是字段访问。作为一个例子而不是

@Id
@GeneratedValue(...)
private long id;

place them on the getters

把它们放在吸气剂上

@Id
@GeneratedValue(...)
public long getId() { ... }

Make sure you make similar changes to the other fields of the Party entity. You can later explore another option of using @Access(AccessType.PROPERTY/FIELD) instead to get the same effect.

确保对Party实体的其他字段进行类似的更改。您可以稍后探索使用@Access(AccessType.PROPERTY/FIELD)的另一个选项,以获得相同的效果。

Moving on to the EAGER

继续前往EAGER

But if I change the fetch type to Eager, then the log.debug() gives me the ID perfectly.

但是如果我将fetch类型更改为Eager,那么log.debug()会完美地为我提供ID。

This is because the FetchType.EAGER results in fetching the party entity eagerly (no proxy) up front and so we are able to get the id and other properties of party entity. Note that, this results in either a JOIN/extra SELECT query based on configuration.

这是因为FetchType.EAGER导致预先获取派对实体(无代理),因此我们能够获得派对实体的id和其他属性。请注意,这会导致基于配置的JOIN / extra SELECT查询。

Am I wrong at anything???

我什么都错了???

I don't see anything wrong here and it is all because the field vs getter access type have different behavior. So if you are using filed level access, the Hibernate would initialize the proxy even for getting the id of an associated object as per the bug HHH-3718 or until it gets resolved.

我没有看到任何错误,这是因为字段vs getter访问类型具有不同的行为。因此,如果您正在使用文件级别访问,Hibernate将初始化代理,即使是根据错误HHH-3718获取关联对象的ID或直到它得到解决。

And a related topic on hibernate forum regarding field vs property access type that might be of interest Field Vs Property access

关于字段与属性访问类型的hibernate论坛上的相关主题可能是Field Vs Property访问的关注点

Hope this answers your query.

希望这能回答您的疑问。