我的应用中有用户和联系实体,我需要每个用户都可以添加一些关于每个联系人的私人评论,并且该评论必须仅适用于那个用户。所以我创建了新的实体 - PrivateInfo 。这是代码。
用户类:
@Entity
@Table(name = "users")
@XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String login;
// other fields
}
联系班级:
@Entity
@Table(name = "contacts")
@XmlAccessorType(XmlAccessType.FIELD)
public class Contact implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "contact")
private Set<PrivateInfo> privateInfo;
// etc.
}
PrivateInfo类:
@Entity
@Table(name = "private_info")
@XmlAccessorType(XmlAccessType.FIELD)
public class PrivateInfo implements Serializable {
@EmbeddedId
private PrivateInfoKey pk;
@Column(name = "additional_info")
private String additionalInfo;
@ManyToOne(fetch = FetchType.EAGER)
@MapsId("contactId")
private Contact contact;
}
@Embeddable
public class PrivateInfoKey implements Serializable {
@Column(name = "contact_id")
private Long contactId;
@Column(name = "user_id")
private Long userId;
}
我正在使用带有 JpaSpecificationExecutor 的Spring Data存储库进行查询,所以这是我尝试编写规范以获取特定用户的私人信息的所有联系人。
public static Specification<Contact> withPrivateInfo(final long userId) {
return new Specification<Contact>() {
@Override
public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Join<Contact, PrivateInfo> joinPrivateInfo = root.join(Contact_.privateInfo, JoinType.LEFT);
joinPrivateInfo.on(cb.equal(
joinPrivateInfo.get(PrivateInfo_.pk).get(PrivateInfoKey_.userId), userId
));
return cb.conjunction(); // translates in sql like '... where 1 = 1'
}
};
}
然而,当我打电话
contactRepository.findAll(withPrivateInfo(1));
我正在接收联系人,并且每个联系人都在privateInfo字段中包含有关此联系人的所有用户信息(不仅仅是id = 1的用户,如预期的那样)。似乎忽略 join on 条件。
有任何建议如何实现我的目标?也许与另一个实体结构。这可能与JPA / Criteria有关吗?