Java JPA只返回@ManyToOne对象的第一个实例 问题
我有两个对象,Java JPA只返回@ManyToOne对象的第一个实例 问题,java,json,spring,hibernate,jpa,Java,Json,Spring,Hibernate,Jpa,我有两个对象,Deck和Card,它们具有多对多关系。联接表的实体是DeckCard,它包含一个嵌入式idDeckCard,以便于从内部组对象访问卡,而无需创建无限循环。(所有代码如下所示。) 当我使用JpaRepository.findAll()检索所有卡片组时,我正确地收到了所有卡片组的列表,每个卡片组都有一个包含卡片列表的属性。深入查看DeckCard.id.card时,我希望看到完整的card对象及其所有属性,如下所示: [ { "id":1, "
Deck
和Card
,它们具有多对多关系。联接表的实体是DeckCard
,它包含一个嵌入式idDeckCard
,以便于从内部组对象访问卡,而无需创建无限循环。(所有代码如下所示。)
当我使用JpaRepository.findAll()
检索所有卡片组时,我正确地收到了所有卡片组的列表,每个卡片组都有一个包含卡片列表的属性。深入查看DeckCard.id.card
时,我希望看到完整的card
对象及其所有属性,如下所示:
[
{
"id":1,
"name":"Deck 1",
"cards":[
{
"id":{
"deck":1,
"card":{
"id":1,
"name":"Card 1"
}
},
...
},
{
"id":{
"deck":1,
"card":{
"id":2,
"name":"Card 2"
}
},
...
}
]
},
{
"id":2,
"name":"Deck 2",
"cards":[
{
"id":{
"deck":2,
"card":{
"id":1,
"name":"Card 1"
}
},
...
},
{
"id":{
"deck":2,
"card":{
"id":3,
"name":"Card 3"
}
},
...
}
]
},
{
"id":3,
"name":"Deck 3",
"cards":[
{
"id":{
"deck":3,
"card":{
"id":3,
"name":"Card 3"
}
},
...
},
{
"id":{
"deck":3,
"card":{
"id":4,
"name":"Card 4"
}
},
...
}
]
},
]
对于每个卡的第一次出现
,这是正确的;然而,对于该卡在其他牌组中的所有后续外观,我得到的只是该卡的id:
[
{
"id":1,
"name":"Deck 1",
"cards":[
{
"id":{
"deck":1,
"card":{
"id":1,
"name":"Card 1"
}
},
...
},
{
"id":{
"deck":1,
"card":{
"id":2,
"name":"Card 2"
}
},
...
}
]
},
{
"id":2,
"name":"Deck 2",
"cards":[
{
"id":{
"deck":2,
"card":1 // I expected this to be the full model of Card 1
},
...
},
{
"id":{
"deck":2,
"card":{
"id":3,
"name":"Card 3"
}
},
...
}
]
},
{
"id":3,
"name":"Deck 3",
"cards":[
{
"id":{
"deck":3,
"card":3 // I expected this to be the full model of Card 3
},
...
},
{
"id":{
"deck":3,
"card":{
"id":4,
"name":"Card 4"
}
},
...
}
]
},
]
我想这与默认设置有关,以避免不必要的重复,但我在JPA文档中没有找到任何东西来说明为什么会发生这种情况或如何防止这种情况
编辑:
我尝试将Deck.cards
、deckcardd.Deck
和deckcardd.card
更改为eager,得到了相同的结果。然而,在调试过程中我注意到,即使使用FetchType.LAZY
我也会在Eclipse中获得完整的DeckCard.id.card
对象,并且只有在列表
序列化之后,JSON才会包含每个卡后续出现的id。这可能是Jackson序列化问题,而不是JPA问题吗
代码
Deck.java
@Entity
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = Deck.class
)
public class Deck {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@OneToMany(
fetch = FetchType.LAZY,
mappedBy = "id.deck",
cascade = CascadeType.ALL
)
private List<DeckCard> cards;
// standard getters & setters
}
deckcard.java
@Embeddable
public class DeckCardId implements Serializable {
private static final long serialVersionUID = -6470278480687272622L;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Deck deck;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Card card;
// standard getters & setters
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
DeckCardId that = (DeckCardId) o;
if (deck != null ? !deck.equals(that.deck) : that.deck != null)
return false;
if (card != null ? !card.equals(that.card) : that.card != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = (deck != null ? deck.hashCode() : 0);
return 31 * result + (card != null ? card.hashCode() : 0);
}
}
解决方案
虽然我最初没有发布卡片
类的代码,但选择的答案让我意识到它包含与卡片
相同的JsonIdentityInfo
注释:
@Entity
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = Card.class
)
public class Card {
// rest of class
通过从卡
中删除此注释,每个卡
的第一个之后的所有实例都被完整序列化,而不是通过引用进行序列化。前几天我遇到了完全相同的问题。事实证明,这不是JPA的错(您可以在调试器中看到它正确映射了所有实例),而是Jackson序列化程序的错
您需要从类中修改或删除JsonIdentityInfo
,突然所有实例都将映射它们的关系 它被定义为懒惰。除非调用get方法,否则不会加载详细信息。尝试更改为“渴望”并查看行为。@谢谢您的建议!我将编辑这个问题,但简短的回答是,它产生了相同的结果。这正是我所需要的。我没有把Card
的代码放进去(我会编辑这个问题),但是它还有JsonIdentityInfo
,这导致第一个之后的所有实例都通过引用而不是全部序列化。
@Entity
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = Card.class
)
public class Card {
// rest of class