多对一连接表使用Jersey的JAX-RS的休眠资源类中 [英] Many-To-One with join Table in hibernate resource classes for a JAX-RS using Jersey

查看:145
本文介绍了多对一连接表使用Jersey的JAX-RS的休眠资源类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Jersey实现一个RESTful Web服务。我使用hibernate与数据库(mySQL)进行通信。我的hibernate资源类包括:

  @Entity 
public class Activity {

@Id
@GeneratedValue
私人长ID;

@ManyToOne
@JoinTable(name =category_activity,
joinColumns = {@ JoinColumn(name =activities_id)},
inverseJoinColumns = {@ JoinColumn (name =Category_id)})
私人类别类别;
}

和Category类别:

  @Entity 
public class Category {

@Id
@GeneratedValue
private long id;

@OneToMany
@Fetch(FetchMode.JOIN)
@JoinTable(name =category_activity,
joinColumns = {@JoinColumn(name =Category_id)) },
inverseJoinColumns = {@JoinColumn(name =activities_id)})
@JsonIgnore
private Collection< Activity>活动;
}

我使用这个查询来获取活动:

  session.createQuery(from Activity a join a.category cs where cs.id =:categoryId order by a.key)。setLong(categoryId ,categoryId).list(); 

JSON格式的结果并不正确:

  [[{id:26,key:other,name:Other,cost:100.0,category:{ id:10,name:General,description:}},{id:10,name:General,description:}]] 

正如您所看到的类别打印了2次,并且我们有一个额外的[]。
当我在Category类中使用另一种One-To-Many关系机制时:

$ p $ @OneToMany(targetEntity = Activity.class,mappedBy =category,fetch = FetchType.LAZY,cascade = CascadeType.ALL)
@JsonIgnore
private Collection< Project>活动;

而在Activity类中:

  @ManyToOne(可选= false)
私人类别类别;

此查询:

  session.createQuery(from Activity as a where a.category.id =:categoryId order by a.key)。setLong(categoryId,categoryId).list(); 

一切正常。但我必须使用连接表,因为我不想更改数据库。



正确的结果应该如下所示:

  [{id:26,key:other,name:Other,cost:100.0,category:{id :10,name:General,description:}}] 

解决方案

在多方面定义连接表,但不要再次定义连接表一边。这会创建两个映射到同一个表的单向关联,而不是一个双向关联。

双向关联总是拥有所有者一方(您指定要使用的连接列或连接表,而反面则表示帽子是另一面的反面通过使用mappedBy属性:

  public class Activity {

@ManyToOne //所有者方:它没有mappedBy,并且可以决定如何映射关联:使用连接表
@JoinTable(name =category_activity,
joinColumns = {@ JoinColumn(name =activities_id))},
inverseJoinColumns = {@ JoinColumn(name =Category_id)})
private Category category;
}

public class Category {
@OneToMany( mappedBy =category)//反面:它有一个mappedBy属性,并且不能决定这个关联是如何映射的,因为另一面已经决定了它。
@Fetch(FetchMode.JOIN)
@JsonIgnore
private Collection< Activity> activities;
}

编辑:

另外,您的查询应该只选择活动,而不是查询所加入的所有实体,一个select子句:

 从一个活动中选择a作为其中a.category.id =:categoryId按a.key排序


I am implementing a RESTful Web Service using Jersey. I use hibernate to communicate with the database (mySQL). My hibernate resource classes includes:

@Entity
public class Activity {

    @Id
    @GeneratedValue
    private long id;

@ManyToOne
    @JoinTable(name="category_activity",
    joinColumns={@JoinColumn(name="activities_id")},
    inverseJoinColumns={@JoinColumn(name="Category_id")})
    private Category category;
}

and the Category class:

@Entity
public class Category {

    @Id
    @GeneratedValue
    private long id;

    @OneToMany
    @Fetch(FetchMode.JOIN)
    @JoinTable(name = "category_activity",
    joinColumns = { @JoinColumn(name = "Category_id") }, 
    inverseJoinColumns = { @JoinColumn(name = "activities_id") })
    @JsonIgnore
    private Collection<Activity> activities;
}

I used this query to fetch the ativities:

session.createQuery("from Activity a join a.category cs where cs.id= :categoryId order by a.key").setLong("categoryId", categoryId).list();

The result in JSON format is not right like:

[[{"id":26,"key":"other","name":"Other","cost":100.0,"category":{"id":10,"name":"General","description":""}},{"id":10,"name":"General","description":""}]]

As you see category is printed 2 times and we have a extra [] around it. When I use another mechanism of One-To-Many relation in Category class like:

@OneToMany(targetEntity = Activity.class, mappedBy = "category", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonIgnore
private Collection<Project> activities;

And in Activity class:

@ManyToOne(optional = false)
    private Category category;

And this query:

session.createQuery("from Activity as a where a.category.id= :categoryId order by a.key").setLong("categoryId", categoryId).list();

Everything works fine. But I have to use join table because I do not suppose to change the database.

The proper result should look like:

[{"id":26,"key":"other","name":"Other","cost":100.0,"category":{"id":10,"name":"General","description":""}}]

I appreciate for any help.

解决方案

Define the join table on the many side, but don't define it once again on the one side. This creates two unidirectional associations mapped with the same table instead of one bidirectional association.

A bidirectional association always has an owner side (where you specify the join column or join table to use, and an inverse side which says hat it's the inverse of the other side by using the mappedBy attribute:

public class Activity {

    @ManyToOne // owner side: it doesn't have mappedBy, and can decide how the association is mapped: with a join table
    @JoinTable(name="category_activity",
               joinColumns={@JoinColumn(name="activities_id")},
               inverseJoinColumns={@JoinColumn(name="Category_id")})
    private Category category;
}

public class Category {
    @OneToMany(mappedBy = "category") // inverse side: it has a mappedBy attribute, and can't decide how the association is mapped, since the other side already decided it.
    @Fetch(FetchMode.JOIN)
    @JsonIgnore
    private Collection<Activity> activities;
}

EDIT:

Also, your query should only select the activity, and not all the entities joined by the query, by adding a select clause:

select a from Activity as a where a.category.id= :categoryId order by a.key

这篇关于多对一连接表使用Jersey的JAX-RS的休眠资源类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆