[英]JPA left join query
给出以下两个表:
CREATE TABLE `x` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name_hash` char(32) NOT NULL,
`access_time` bigint(20) unsigned NOT NULL,
`name` varchar(1024) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_hash` (`name_hash`),
KEY `access_time` (`access_time`),
CONSTRAINT `x_ibfk_1` FOREIGN KEY (`access_time`) REFERENCES `update_time` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `y` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`x` bigint(20) unsigned NOT NULL,
`update_time` bigint(20) unsigned NOT NULL,
`reason` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `x` (`x`,`update_time`),
KEY `reason` (`reason`),
KEY `update_time` (`update_time`),
CONSTRAINT `y_ibfk_1` FOREIGN KEY (`reason`) REFERENCES `reason` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `y_ibfk_2` FOREIGN KEY (`x`) REFERENCES `x` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `y_ibfk_3` FOREIGN KEY (`update_time`) REFERENCES `update_time` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我使用NetBeans创建了以下JPA类(X和Y不是真实名称,以为我做了所有必需的更改):
@Entity
@Table(name = "X", catalog = "topiclymobile", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"name_hash"})})
@NamedQueries({
@NamedQuery(name = "X.findAll", query = "SELECT t FROM X t"),
@NamedQuery(name = "X.findById", query = "SELECT t FROM X t WHERE t.id = :id"),
@NamedQuery(name = "X.findByNameHash", query = "SELECT t FROM X t WHERE t.nameHash = :nameHash"),
@NamedQuery(name = "X.findByName", query = "SELECT t FROM X t WHERE t.name = :name")})
public class X implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id", nullable = false)
private Long id;
@Basic(optional = false)
@Column(name = "name_hash", nullable = false, length = 32)
private String nameHash;
@Basic(optional = false)
@Column(name = "name", nullable = false, length = 1024)
private String name;
@JoinColumn(name = "access_time", referencedColumnName = "id", nullable = false)
@ManyToOne(optional = false)
private UpdateTime accessTime;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "X")
private List<Y> YList;
public X() {
}
public X(Long id) {
this.id = id;
}
public X(Long id, String nameHash, String name) {
this.id = id;
this.nameHash = nameHash;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNameHash() {
return nameHash;
}
public void setNameHash(String nameHash) {
this.nameHash = nameHash;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UpdateTime getAccessTime() {
return accessTime;
}
public void setAccessTime(UpdateTime accessTime) {
this.accessTime = accessTime;
}
public List<Y> getYList() {
return YList;
}
public void setYList(List<Y> YList) {
this.YList = YList;
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + (this.nameHash != null ? this.nameHash.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final X other = (X) obj;
if ((this.nameHash == null) ? (other.nameHash != null) : !this.nameHash.equals(other.nameHash)) {
return false;
}
return true;
}
}
@Entity
@Table(name = "Y", catalog = "topiclymobile", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"X", "update_time"})})
@NamedQueries({
@NamedQuery(name = "Y.findAll", query = "SELECT t FROM Y t"),
@NamedQuery(name = "Y.findById", query = "SELECT t FROM Y t WHERE t.id = :id")})
public class Y implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id", nullable = false)
private Long id;
@JoinColumn(name = "reason", referencedColumnName = "id", nullable = false)
@ManyToOne(optional = false)
private Reason reason;
@JoinColumn(name = "X", referencedColumnName = "id", nullable = false)
@ManyToOne(optional = false)
private X X;
@JoinColumn(name = "update_time", referencedColumnName = "id", nullable = false)
@ManyToOne(optional = false)
private UpdateTime updateTime;
public Y() {
}
public Y(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Reason getReason() {
return reason;
}
public void setReason(Reason reason) {
this.reason = reason;
}
public X getX() {
return X;
}
public void setX(X X) {
this.X = X;
}
public UpdateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(UpdateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public int hashCode() {
int hash = 7;
hash = 13 * hash + (this.X != null ? this.X.hashCode() : 0);
hash = 13 * hash + (this.updateTime != null ? this.updateTime.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Y other = (Y) obj;
if (this.X != other.X && (this.X == null || !this.X.equals(other.X))) {
return false;
}
if (this.updateTime != other.updateTime && (this.updateTime == null || !this.updateTime.equals(other.updateTime))) {
return false;
}
return true;
}
}
我所追求的是在所有情况下,“ x”在给定时间内没有对应的“ y”(access_time和update_time是同一件事)。
此SQL查询有效,我似乎无法将其转换为JPA查询:
SELECT t.id FROM x t LEFT JOIN y r ON t.id = r.x WHERE r.x IS NULL AND t.access_time = 1
最好查看您的实体类来构造实际的查询,但是JPA确实支持LEFT JOIN
。 这篇博客文章有一个完整的示例, 这个问题也有 ,但是类似
SELECT x FROM X x LEFT JOIN x.y ...
我不确定查询的其余部分应该是什么,因为您发布的内容看起来不像是有效的SQL(您拥有WHERE rx IS NULL
,但是给定的架构将表y上的x定义为NOT NULL
;类似地,拥有WHERE rx IS NULL
应该使您的左t.id = rx
匹配任何东西,因为t.id = rx
总是计算为NULL
)。
编辑:关于您的示例SQL如何是一个有效的查询,我仍然感到困惑,但是类似这样的东西似乎应该转换为您提供的SQL:
SELECT x FROM X x LEFT JOIN x.yList y where y.x IS NULL and x.accessTime = :accessTime
其中:accessTime
参数是entityManager.getReference(UpdateTime.class, 1)
:accessTime
entityManager.getReference(UpdateTime.class, 1)
。
同样,尽管FROM x LEFT JOIN y on x.id = yx WHERE yx IS NULL
的FROM x LEFT JOIN y on x.id = yx WHERE yx IS NULL
应该精确地匹配Y中的任何行,而(因为它是LEFT JOIN
),它将包括X中的所有行。换句话说,我认为您的查询等同于:
SELECT x.id FROM X where x.access_time = 1
在JPA中是这样的:
SELECT x FROM X x where x.accessTime = :accessTime
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.