[英]How to connect one entity with more than one entity in Spring JPA?
I have some problems in understanding how to connect one entity with others in one attribute.我在理解如何在一个属性中将一个实体与其他实体联系起来时遇到了一些问题。 That is not typical OneToMany relationship, I'm talking about situation when I need to implement complains functionality in my application:
User
can complain about several different entities ( Question
, Answer
, Comment
or another User
), so the Complain
entity will have schema relations like:这不是典型的 OneToMany 关系,我说的是我需要在我的应用程序中实现投诉功能的情况:
User
可以投诉几个不同的实体( Question
、 Answer
、 Comment
或另一个User
),因此Complain
实体将具有模式关系像:
where User connects as One to many to user_id
and Many To One to entity_id
( 1
to *
and *
to 1
in image).其中 User 连接为一对多到
user_id
,多对一连接到entity_id
(图像中的1
到*
和*
到1
)。
So, I tried to use parameterized class Complain
to implement this ( BaseComplain
is empty class):所以,我尝试使用参数化的 class
Complain
来实现这个( BaseComplain
是空类):
Complain.java
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name = "complains")
public class Complain<T extends BaseComplain> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user_id;
@ManyToOne
@JoinColumn(name = "entity_id", nullable = false)
private T entity_id;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date created_on;
}
User.java
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name = "users")
public class User extends BaseComplain {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@OneToMany(mappedBy = "user_id", orphanRemoval = true, fetch = FetchType.LAZY)
@ToString.Exclude
private Set<Complain<BaseComplain>> author_complains;
@OneToMany(mappedBy = "entity_id", orphanRemoval = true, fetch = FetchType.LAZY)
@ToString.Exclude
private Set<Complain<User>> complains;
<...other stuff...>
}
And Question.java
(all entities have the same realisation of relationship):和
Question.java
(所有实体具有相同的关系实现):
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name = "questions")
public class Question extends BaseComplain {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "entity_id", orphanRemoval = true, fetch = FetchType.LAZY)
@ToString.Exclude
@JsonManagedReference
private Set<Complain<Question>> complains;
<...other stuff...>
}
But it caused (formatted):但它导致(格式化):
org.hibernate.AnnotationException:
Property com.*.*.Entities.Complain.entity_id has an unbound type and no explicit target entity.
Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=)
or use an explicit @Type...
I can add all stack trace, but there are only typical spring app exceptions ( Bean creation error
, embedded Tomcat exception
).我可以添加所有堆栈跟踪,但只有典型的 spring 应用程序异常(
Bean creation error
, embedded Tomcat exception
)。
So the question is - Is there any way to implement this logics using only, like, "basic" features of JPA?所以问题是——有没有办法只使用 JPA 的“基本”功能来实现这个逻辑?
Probably, I have some ideas of @MappedSuperclass
usage, but still need your help.可能,我对
@MappedSuperclass
的用法有一些想法,但仍然需要您的帮助。
How about this - it looks like what you have tried to a certain extent;这个怎么样——看起来你在一定程度上已经尝试过了; the idea is that the
Complaint
is an abstract base entity, so that it can have relations to and from it, but the concrete implementations are questions, answers etc. To have a base table and separate ones per complaint type, use @Inheritance(strategy = InheritanceType.JOINED)
.这个想法是
Complaint
是一个抽象的基本实体,因此它可以与它有关系,但具体的实现是问题,答案等。要有一个基表和每个投诉类型分开的基表,请使用@Inheritance(strategy = InheritanceType.JOINED)
。 And use concrete complaint types that are different from the entities they link to, eg QuestionComplaint
→ Question
.并使用不同于它们链接到的实体的具体投诉类型,例如
QuestionComplaint
→ Question
。 So:所以:
@Entity
@Table(name = "complaints")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Complaint {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date created_on;
}
The user in turn relates to a set of Complaint
objects, but is not a Complaint
itself (doesn't make sense, does it?)用户又与一组
Complaint
对象相关,但不是Complaint
本身(没有意义,是吗?)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@OneToMany(mappedBy = "user_id", orphanRemoval = true, fetch = FetchType.LAZY)
@ToString.Exclude
private Set<Complaint> complaints;
}
And the concrete Complaint
instances:以及具体的
Complaint
实例:
@Entity
@Table(name = "question_complaints")
@PrimaryKeyJoinColumn(name = "id")
public class QuestionComplaint extends Complaint {
@ManyToOne(fetch = FetchType.LAZY)
private Question question
}
This entity represents the link from Complaint
to Question
.该实体表示从
Complaint
到Question
的链接。 The Question
entity, which represents a "Question", no matter if it has complaints attached, may optionally have a relation back to the QuestionComplaint
:代表“问题”的
Question
实体,无论是否附加了投诉,都可以选择与QuestionComplaint
建立关系:
@Entity
@Table(name = "questions")
public class Question {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
private List<QuestionComplaint> complaints;
}
Now usages I expect would be:现在我期望的用法是:
User.getComplaints()
will fetch a UNION ALL of the complaints from all known subtypes User.getComplaints()
将从所有已知子类型中获取一个 UNION ALL 投诉question.getComplaints()
knows to get records only from the table question_complaints
question.getComplaints()
知道只从表question_complaints
中获取记录SELECT c FROM QuestionComplaint c WHERE c.user.id =:x AND c.question.id =:y
SELECT c FROM QuestionComplaint c WHERE c.user.id =:x AND c.question.id =:y
Fistly, in java Generic Types
can't deteminable in runtime
, so JPA
can't determine to fetch from which table
, so it will throw Exception
which you send.首先,在 java
Generic Types
can't deteminable in runtime
,所以JPA
不能确定从哪个table
获取,所以它会throw Exception
。
Secodly your database design is wrong, Complain
table will not connect to Question
and Answer
, Question
and Answer
need to connect Complain
.其次你的数据库设计是错误的,
Complain
表不会连接到Question
和Answer
, Question
和Answer
需要连接Complain
。 Like:像:
Quesiton -|
v
---> Complain ---> User
^
Answer -|
Or you need to add to two fields to Complain
table like questionId
and answerId
.或者您需要将两个字段添加到
Complain
表中,例如questionId
和answerId
。
Q u e s i t o n A n s w e r
^ ^
| |
(questionID) (answerId)
| |
+-----------Complain ---> User
One field two foreign table not good design specially for JPA.一域二外表不好专门为JPA设计的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.