我有以下表结构:用户,对话,消息。用户具有对话框列表和消息列表。 Dialog包含用户列表和消息列表。而Message则引用了对话框和用户。所以
用户 - 对话框:many to many
,
消息 - 用户:many to one
,
消息 - 对话many to one
实体:
对话框
@Entity
@Table(name = "dialogs")
public class Dialog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_dialog")
private Long id;
@Column(name = "dialog_name")
private String dialogName;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "dialogs_users",
joinColumns = @JoinColumn(name = "id_dialog"),
inverseJoinColumns = @JoinColumn(name = "id_user"))
private List<User> dialogUsers;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "dialog")
private List<Message> messages = new ArrayList<>();
//default constructor and getters setters and hashCode equals toString
}
用户
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_user")
private Long id;
@NotNull
@Column(name = "full_name")
private String fullName;
@NotNull
@Column(name = "email")
private String email;
@NotNull
@Column(name = "active")
private boolean active;
@NotNull
@Column(name = "password")
private String password;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
private List<Message> messages;
@ElementCollection(targetClass = Role.class)
@CollectionTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user"))
@Column(name = "role")
@Enumerated(EnumType.ORDINAL)
private List<Role> roles = new ArrayList<>();
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "dialogUsers")
private List<Dialog> dialogs = new ArrayList<>();
//default constructor and getters setters and hashCode equals toString
}
消息
@Entity
@Table(name = "messages")
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_message")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_dialog")
private Dialog dialog;
@Column(name = "value")
private String value;
@Column(name = "date_time")
private LocalDateTime dateTime;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_user")
private User user;
//default constructor and getters setters and hashCode equals toString
}
我的entityManager查询
@Override
public List<Message> findMessagesByDialog(Long dialogId) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Message> criteria = builder.createQuery(Message.class);
Root<Dialog> dialog = criteria.from(Dialog.class);
Join<Dialog, Message> messages = dialog.join(Dialog_.messages);
criteria.select(messages).where(builder.equal(dialog.get(Dialog_.id), dialogId));
return entityManager.createQuery(criteria).getResultList();
}
执行此查询时我得到的堆栈跟踪
Hibernate:
select
messages1_.id_message as id_messa1_2_,
messages1_.date_time as date_tim2_2_,
messages1_.id_dialog as id_dialo4_2_,
messages1_.id_user as id_user5_2_,
messages1_.value as value3_2_
from
dialogs dialog0_
inner join
messages messages1_
on dialog0_.id_dialog=messages1_.id_dialog
where
dialog0_.id_dialog=1
Hibernate:
select
dialog0_.id_dialog as id_dialo1_0_0_,
dialog0_.dialog_name as dialog_n2_0_0_
from
dialogs dialog0_
where
dialog0_.id_dialog=?
Hibernate:
select
user0_.id_user as id_user1_4_0_,
user0_.active as active2_4_0_,
user0_.email as email3_4_0_,
user0_.full_name as full_nam4_4_0_,
user0_.password as password5_4_0_
from
users user0_
where
user0_.id_user=?
Hibernate:
select
user0_.id_user as id_user1_4_0_,
user0_.active as active2_4_0_,
user0_.email as email3_4_0_,
user0_.full_name as full_nam4_4_0_,
user0_.password as password5_4_0_
from
users user0_
where
user0_.id_user=?
Hibernate:
select
dialoguser0_.id_dialog as id_dialo1_1_0_,
dialoguser0_.id_user as id_user2_1_0_,
user1_.id_user as id_user1_4_1_,
user1_.active as active2_4_1_,
user1_.email as email3_4_1_,
user1_.full_name as full_nam4_4_1_,
user1_.password as password5_4_1_
from
dialogs_users dialoguser0_
inner join
users user1_
on dialoguser0_.id_user=user1_.id_user
where
dialoguser0_.id_dialog=?
..等等
我知道我有多个引用,一个实体引用另一个,但所有提取都是懒惰的。而且你也可以认为问题出在方法 hashCode,equals或toString 中,它们没有引用另一个实例(只有自己的字段)。
我不排除我在我的实体声明中的某个地方弄错了
答案 0 :(得分:0)
您可以在dialogUsers
实体中使用杰克逊的@JsonIgnore annotation和Dialog
列表,这样可以防止Hibernate在选择Dialog
时为用户提取列表:
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "dialogs_users",
joinColumns = @JoinColumn(name = "id_dialog"),
inverseJoinColumns = @JoinColumn(name = "id_user"))
@JsonIgnore
private List<User> dialogUsers;