Hibernate和Jackson的多对多关系,带有额外字段。

huangapple go评论76阅读模式
英文:

Hibernate and Jackson manyToMany relation with extra fields

问题

最近我一直在尝试通过多对多关系链接一个Module表和一个Activity表。这种关系引入了一个额外的字段,如下所示。

-------------------------------------------------------------
| Module      |   ModuleHasActivities  |     Activities    |
-------------------------------------------------------------
| id          |  Module_idModule      |    id             |    
| Name        |  Activity_idActivity  |    Name           |
| Observations  |  Day                 |    Price          |
-------------------------------------------------------------

我使用JsonManagedReference和JsonBackReference来避免无限循环。不幸的是,结果并不是预期的,因为我无法从activities获取到modules列表,反之亦然。返回的唯一信息是实体字段。

@Entity
@Table(name = "Module")
public class Module implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "idModule")
    private int id;
    
    // 其他字段加上getter和setter

    @OneToMany(mappedBy = "module", cascade = CascadeType.ALL)
    @JsonBackReference
    private Set<ModuleHasActivities> moduleHasActivities = new HashSet<>();
}
@Entity
@Table(name = "Activite")
public class Activite implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "idActivite")
    private int id;

    // 其他字段

    @OneToMany(mappedBy = "activite", cascade = CascadeType.ALL)
    @JsonBackReference
    private Set<ModuleHasActivities> moduleHasActivities = new HashSet<>();
}
@Entity
@Table(name = "Module_has_Activite")
public class ModuleHasActivities implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name = "Module_idModule")
    @JsonManagedReference
    private Module module;

    @Id
    @ManyToOne
    @JoinColumn(name = "Activite_idActivite")
    @JsonManagedReference
    private Activite activite;

    @Column(name = "IdJour")
    private int jour;
}

查询模块的响应:

[
    {
        "id": 1,
        "code": "TT1",
        "title": "Test 1",
        "description": "Nothing",
        "observations": "Nothing"
    }
]

我期望的结果(类似于这样):

[
    {
        "id": 1,
        "code": "TT1",
        "title": "Test 1",
        "description": "Nothing",
        "observations": "Nothing",
        "activities": [
            "day1": {
                // activities的字段
            },
            "day2": {
                // activities的字段
            }
        ]
    }
]

当我调试Hibernate的SQL查询时,我们可以看到连接从未执行。这正是我所关心的!连接到模块表的连接丢失了。

对此有一点帮助将不胜感激,

谢谢

已访问链接:
Extra fields for many to many relations

英文:

Recently I've been trying to link a Module table and an Activity table by a Many to Many relationship.
This relation welcomes an additional field as below.

-------------------------------------------------------------
| Module	    |   ModuleHasActivities	|     Activities    |
-------------------------------------------------------------
| id	        |  Module_idModule	    |	id	            |	
| Name	        |  Activity_idActivity	|	Name            |
| Observations  |  Day			        |	Price           |
-------------------------------------------------------------

I use JsonManagedReference and JsonBackReference to avoid infinite loops. Unfortunately the result is not the expected one since I don't get the list of modules from the activities and vice versa. The only information returned are the entity fields.

@Entity
@Table(name = &quot;Module&quot;)
public class Module implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = &quot;idModule&quot;)
    private int id;
    
    // Other fields plus getter and setter

    @OneToMany(mappedBy = &quot;module&quot;, cascade = CascadeType.ALL)
    @JsonBackReference
    private Set&lt;ModuleHasActivities&gt; moduleHasActivities = new HashSet&lt;&gt;();
}
@Entity
@Table(name = &quot;Activite&quot;)
public class Activite implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = &quot;idActivite&quot;)
    private int id;

    // Other fields

    @OneToMany(mappedBy = &quot;activite&quot;, cascade = CascadeType.ALL)
    @JsonBackReference
    private Set&lt;ModuleHasActivities&gt; moduleHasActivities = new HashSet&lt;&gt;();
}
@Entity
@Table(name = &quot;Module_has_Activite&quot;)
public class ModuleHasActivities implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name = &quot;Module_idModule&quot;)
    @JsonManagedReference
    private Module module;

    @Id
    @ManyToOne
    @JoinColumn(name = &quot;Activite_idActivite&quot;)
    @JsonManagedReference
    private Activite activite;

    @Column(name = &quot;IdJour&quot;)
    private int jour;

}

Query modules response:

[
    {
        &quot;id&quot;: 1,
        &quot;code&quot;: &quot;TT1&quot;,
        &quot;title&quot;: &quot;Test 1&quot;,
        &quot;description&quot;: &quot;Nothing&quot;,
        &quot;observations&quot;: &quot;Nothing&quot;,
    }
]

What I expect (something like this) :

[
    {
        &quot;id&quot;: 1,
        &quot;code&quot;: &quot;TT1&quot;,
        &quot;title&quot;: &quot;Test 1&quot;,
        &quot;description&quot;: &quot;Nothing&quot;,
        &quot;observations&quot;: &quot;Nothing&quot;,
	    &quot;activities&quot;: [
	      &quot;day1&quot;: 
		  {
		   //fields of activities
		  },
	      &quot;day2&quot;: 
		  {
		   //fields of activities
		  },
	]
    }
]

When I debug hibernate's SQL queries, we see that the join is never done. And that's what interests me! Joints to the module table are missing.
Hibernate和Jackson的多对多关系,带有额外字段。

A little help would be appreciated,

Thank you

Already visited links :
Extra fields for many to many relations

答案1

得分: 0

你需要理解 JsonManagedReferenceJsonBackReference 之间的区别。详见:https://stackoverflow.com/a/37394318/607637。

@Entity
public class Module  {
    @JsonBackReference
    private Set<ModuleHasActivities> moduleHasActivities = new HashSet<>();
}

@Entity
public class ModuleHasActivities implements Serializable {
    @JsonManagedReference
    private Module module;
}

在这里,如果你序列化 Module 对象,你的 JSON 中将不会包含 moduleHasActivities 字段,但是如果你序列化 ModuleHasActivities 对象,你将会得到 module 字段。

所以,解决方案是将 @JsonBackReference@JsonManagedReference 进行调换,如下所示:

@Entity
public class Module  {
    @JsonManagedReference
    private Set<ModuleHasActivities> moduleHasActivities = new HashSet<>();
}

@Entity
public class ModuleHasActivities implements Serializable {
    @JsonBackReference
    private Module module;
}
英文:

You need to understand the differences between JsonManagedReference and JsonBackReference. See this: https://stackoverflow.com/a/37394318/607637 for more info.

@Entity
public class Module  {
    @JsonBackReference
    private Set&lt;ModuleHasActivities&gt; moduleHasActivities = new HashSet&lt;&gt;();
}

@Entity
public class ModuleHasActivities implements Serializable {
    @JsonManagedReference
    private Module module;
}

Here, if you serialize Module object, you will not get moduleHasActivities field in json but if you serialize ModuleHasActivities object you will get module field.

So, the solution is to flip the @JsonBackReference and @JsonManagedReference as below:

@Entity
public class Module  {
    @JsonManagedReference
    private Set&lt;ModuleHasActivities&gt; moduleHasActivities = new HashSet&lt;&gt;();
}

@Entity
public class ModuleHasActivities implements Serializable {
    @JsonBackReference
    private Module module;
}

答案2

得分: 0

终于,我解决了我的问题。我不再使用复合键,而是将我的数据库模型更改为使用主 id 键和两个指向我关注的表的引用。映射更简单,我可以获取到所需信息。

英文:

Finally, I solved my problem. Instead of using a composite key, I changed my database model to use a primary id key and 2 references to my concerned tables. Mapping is easier and I get my information.

huangapple
  • 本文由 发表于 2020年10月22日 22:06:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64484008.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定