hibernate - Join Fetch JPQL 返回一个代理对象,与 Hibernate 一起使用
问题描述
实体:
public class PlayerDetails implements Serializable{
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "batting_stat_id", referencedColumnName = "id")
private BattingStats battingStats;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "bowling_stat_id", referencedColumnName = "id")
private BowlingStats bowlingStats;
}
存储库代码:
String queryString = "select p from PlayerDetails p inner join fetch p.battingStats b where p.name = :name";
TypedQuery<PlayerDetails> query = entityManager.createQuery(queryString, PlayerDetails.class);
query.setParameter("name", name);
PlayerDetails playerDetails = query.getSingleResult();
String queryString2 = "select p from PlayerDetails p inner join fetch p.bowlingStats b where p.name = :name";
TypedQuery<PlayerDetails> query2 = entityManager.createQuery(queryString2, PlayerDetails.class);
query2.setParameter("name", name);
PlayerDetails resultList2 = query2.getSingleResult();
playerDetails.setBowlingStats(resultList2.getBowlingStats());
return Optional.ofNullable(playerDetails);
我正在使用 JOIN FETCH 获取 BattingsStats 和 Bowling Stats,查询被正确触发,第一次获取 PlayerDetails 字段以及 BattingStats 字段。
第二个查询获取 PlayerDetails 和 BowlingStats 字段。但是当我检查每个获取的对象时,BowlingStat 被延迟加载并返回一个代理。在序列化时,我得到:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor
and no properties discovered to create BeanSerializer (to avoid exception, disable
SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain:
com.example.model.response.ResponseModel["playerDetails"]-
com.example.entity.PlayerDetails["bowlingStats"]-
com.example.entity.BowlingStats$HibernateProxy$5RK3X4j1["hibernateLazyInitializer"])
被触发的查询:
select playerdeta0_.id as id1_2_0_,
battingsta1_.id as id1_0_1_,
playerdeta0_.batting_stat_id as batting_7_2_0_,
playerdeta0_.bowling_stat_id as bowling_8_2_0_,
playerdeta0_.name as name2_2_0_,
playerdeta0_.nationality as national3_2_0_,
playerdeta0_.role as role4_2_0_,
playerdeta0_.team as team5_2_0_,
playerdeta0_.value as value6_2_0_,
battingsta1_.batting_average as batting_2_0_1_,
battingsta1_.centuries as centurie3_0_1_,
battingsta1_.fours as fours4_0_1_,
battingsta1_.half_centuries as half_cen5_0_1_,
battingsta1_.highest_score as highest_6_0_1_,
battingsta1_.innings as innings7_0_1_,
battingsta1_.matches as matches8_0_1_,
battingsta1_.sixes as sixes9_0_1_,
battingsta1_.strike_rate as strike_10_0_1_
from player_details playerdeta0_
inner join batting_stats battingsta1_
on playerdeta0_.batting_stat_id=battingsta1_.id
where playerdeta0_.name=?
select playerdeta0_.id as id1_2_0_,
bowlingsta1_.id as id1_1_1_,
playerdeta0_.batting_stat_id as batting_7_2_0_,
playerdeta0_.bowling_stat_id as bowling_8_2_0_,
playerdeta0_.name as name2_2_0_,
playerdeta0_.nationality as national3_2_0_,
playerdeta0_.role as role4_2_0_,
playerdeta0_.team as team5_2_0_,
playerdeta0_.value as value6_2_0_,
bowlingsta1_.balls_bowled as balls_bo2_1_1_,
bowlingsta1_.economy as economy3_1_1_,
bowlingsta1_.five_wicket_haul as five_wic4_1_1_,
bowlingsta1_.wickets as wickets5_1_1_
from player_details playerdeta0_
inner join bowling_stats bowlingsta1_
on playerdeta0_.bowling_stat_id=bowlingsta1_.id
where playerdeta0_.name=?
有人可以帮我弄这个吗?
PS:错误不是hibernate,错误是Jackson尝试解析数据时;现在,我只是直接返回实体。
我的问题不是如何消除这个错误?我的问题是为什么休眠的这种行为?虽然我在同一个会话中多次获取相同的记录(正如亚历克斯所说的那样是一个糟糕的模式,我改变了它,但是由于糟糕的臭代码,我可以在这里学到一些东西!!!)我正在获取相同的记录在同一个会话中有两个不同的查询,尽管触发了两个不同的查询来获取关联,为什么第二个关联总是被视为代理(就像延迟加载一样)-我说第二个获取的关联,因为正如 @Alex 提到的,我交换了查询和相同的问题现在关联第二。尽管有两个不同的查询触发(这是正确的),但我得到了这个。我认为这与会话管理持久实体有关。请让我知道或任何文章,
谢谢。
解决方案
如果您在同一持久性单元的上下文中使用查询两次获取同一实体,那么第二次您将获得该实体的完全相同的实例(请注意,PlayerDetails
两种情况下的对象 ID 都是相同的)。因此,第二个查询中的 JOIN FETCH 不可能有任何效果。
也很明显,为什么 JPA 被设计为永远不允许同一实体的两个实例进入单个持久性上下文:如果您调用playerDetails.setName("John")
and resultList2.setName("Gary")
,哪个版本在持久化时“获胜”?
推荐阅读
- db2 - 云上的 DB2:: 错误: HWCSEC0009E: 调用状态 RESTful api 失败
- python - 装饰器改变对象的状态
- java - 如何在 AndroidStudioProject 的 Java 应用程序中使用 kotlinOptions?
- pandas - 在 Join 函数中进行迭代
- ios - 列表小部件未显示在从 testflight 下载的应用程序中。但是当我在 iPhone Xr 测试设备中运行时它就在那里
- mysql - 使用带空格的 System() 调用的 Ruby MySQL 备份
- python - 使用 keras ResNet50 模型进行二进制分类的输出层
- jquery - Jquery - 预加载器无法正常工作的 CSS 延迟
- discord.py - 使用其 id 向特定服务器发送消息 - discord.py
- azure - 我是否需要单独的应用程序 ID 才能与每个客户的 Azure Active Directory 集成?