spring 数据中的实体关联问题
Issue with entity association in spring data
我有三个实体 DrmAdvertisement
、 DrmCategoryAdvertisement
和 DrmCategory
。现在我想在我的存储库中执行以下数据库查询,
SELECT a.*
FROM drm_advertisement a
JOIN drm_category_advertisement ac ON ac.adid = a.adid
where a.adtype = 'National'
and ac.categoryid = 2;
所以我为 DrmAdvertisement
创建了存储库,如下所示,
public interface AdvertisementRepository extends
CrudRepository<DrmAdvertisement, Long> {
@Query("SELECT a FROM DrmAdvertisement a join DrmCategoryAdvertisement ac ON ac.adid = a.adid where a.adType = :adType and ac.categoryid = :categoryid")
public List<DrmAdvertisement> findAdByCategory(@Param("adType") String adType, @Param("categoryid") Long categoryid);
}
但正如我们所知,JPQL 连接依赖于实体之间的关联,而不是依赖于 ON 子句。那么如何编写不带 ON 子句的查询?
我的代码中是否遗漏了其他内容?我收到以下错误,
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [SELECT a FROM com.dooreme.domain.DrmAdvertisement a join DrmCategoryAdvertisement ac ON ac.adid = a.adid where a.adType = :adType and ac.categoryid = :categoryid]
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1679)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
我的实体 类 是,
Drm广告:
@Entity
@Table(name = "drm_advertisement")
public class DrmAdvertisement implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private long adId;
@Column(nullable = false)
private UUID uuid;
@Column(nullable = true)
private String adName;
@Column(nullable = true)
private String adDetails;
@Column(nullable = true)
private String adType;
@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "drm_category_advertisement", joinColumns = @JoinColumn(name = "adid"), inverseJoinColumns = @JoinColumn(name = "categoryId"))
private DrmCategory drmCategory;
}
Drm类别
@Entity
@Table(name = "drm_category")
@NamedQuery(name = "DrmCategory.findAll", query = "SELECT d FROM DrmCategory d")
public class DrmCategory implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private long categoryId;
@Column(nullable = false)
private UUID uuid;
@Column(nullable = true)
private String categoryName;
@Column(nullable = false)
private long parentId;
@Column(nullable = true)
private String path;
@Column(nullable = true)
private Date createDate;
@Column(nullable = true)
private Date modifiedDate;
@Column(nullable = true)
private boolean active;
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "drm_category_advertisement", joinColumns = @JoinColumn(name = "categoryId"), inverseJoinColumns = @JoinColumn(name = "adid"))
private Set<DrmAdvertisement> drmAdvertisementSet;
}
DrmCategoryAdvertisement
@Entity
@Table(name = "drm_category_advertisement")
@NamedQuery(name = "DrmCategoryAdvertisement.findAll", query = "SELECT d FROM DrmCategoryAdvertisement d")
public class DrmCategoryAdvertisement implements Serializable{
private static final long serialVersionUID = 1L;
@EmbeddedId
private CatAdvId catAdvId;
// bi-directional many-to-one association to DrmAdvertisement
@OneToOne
@JoinColumn(name = "adId", referencedColumnName = "adid", insertable = false, updatable = false)
private DrmAdvertisement drmAdvertisement;
// bi-directional many-to-one association to DrmSubscriber
@OneToOne
@JoinColumn(name = "categoryId", referencedColumnName = "categoryid", insertable = false, updatable = false)
private DrmCategory drmCategory;
}
CatAdvId
@Embeddable
public class CatAdvId implements Serializable {
private static final long serialVersionUID = 1L;
private static final int THIRTYTWO = 32;
private static final int THIRTYTHREE = 32;
private long categoryId;
private long adId;
public CatAdvId()
{
}
public CatAdvId(long categoryId, long adId)
{
this.categoryId = categoryId;
this.adId = adId;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (adId ^ (adId >>> THIRTYTWO));
result = prime * result + (int) (categoryId ^ (categoryId >>> THIRTYTHREE));
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CatAdvId other = (CatAdvId) obj;
if (adId != other.adId)
return false;
if (categoryId != other.categoryId)
return false;
return true;
}
}
您必须映射 DrmAdvertisement 和 DrmCategoryAdvertisement 之间的关系,那么您的查询将是:
SELECT a FROM DrmAdvertisement a where a.adType = :adType and a.drmCategory.categoryId = :categoryid
编辑:
您可以删除映射 DrmCategoryAdvertisement 和 CatAdvId,并在 DrmCategory 中使用 'mappedBy':
@OneToMany(fetch = FetchType.LAZY, mappedBy = "drmCategory")
private Set<DrmAdvertisement> drmAdvertisementSet;
我有三个实体 DrmAdvertisement
、 DrmCategoryAdvertisement
和 DrmCategory
。现在我想在我的存储库中执行以下数据库查询,
SELECT a.*
FROM drm_advertisement a
JOIN drm_category_advertisement ac ON ac.adid = a.adid
where a.adtype = 'National'
and ac.categoryid = 2;
所以我为 DrmAdvertisement
创建了存储库,如下所示,
public interface AdvertisementRepository extends
CrudRepository<DrmAdvertisement, Long> {
@Query("SELECT a FROM DrmAdvertisement a join DrmCategoryAdvertisement ac ON ac.adid = a.adid where a.adType = :adType and ac.categoryid = :categoryid")
public List<DrmAdvertisement> findAdByCategory(@Param("adType") String adType, @Param("categoryid") Long categoryid);
}
但正如我们所知,JPQL 连接依赖于实体之间的关联,而不是依赖于 ON 子句。那么如何编写不带 ON 子句的查询?
我的代码中是否遗漏了其他内容?我收到以下错误,
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [SELECT a FROM com.dooreme.domain.DrmAdvertisement a join DrmCategoryAdvertisement ac ON ac.adid = a.adid where a.adType = :adType and ac.categoryid = :categoryid]
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1679)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608)
org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
我的实体 类 是,
Drm广告:
@Entity
@Table(name = "drm_advertisement")
public class DrmAdvertisement implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private long adId;
@Column(nullable = false)
private UUID uuid;
@Column(nullable = true)
private String adName;
@Column(nullable = true)
private String adDetails;
@Column(nullable = true)
private String adType;
@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "drm_category_advertisement", joinColumns = @JoinColumn(name = "adid"), inverseJoinColumns = @JoinColumn(name = "categoryId"))
private DrmCategory drmCategory;
}
Drm类别
@Entity
@Table(name = "drm_category")
@NamedQuery(name = "DrmCategory.findAll", query = "SELECT d FROM DrmCategory d")
public class DrmCategory implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private long categoryId;
@Column(nullable = false)
private UUID uuid;
@Column(nullable = true)
private String categoryName;
@Column(nullable = false)
private long parentId;
@Column(nullable = true)
private String path;
@Column(nullable = true)
private Date createDate;
@Column(nullable = true)
private Date modifiedDate;
@Column(nullable = true)
private boolean active;
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "drm_category_advertisement", joinColumns = @JoinColumn(name = "categoryId"), inverseJoinColumns = @JoinColumn(name = "adid"))
private Set<DrmAdvertisement> drmAdvertisementSet;
}
DrmCategoryAdvertisement
@Entity
@Table(name = "drm_category_advertisement")
@NamedQuery(name = "DrmCategoryAdvertisement.findAll", query = "SELECT d FROM DrmCategoryAdvertisement d")
public class DrmCategoryAdvertisement implements Serializable{
private static final long serialVersionUID = 1L;
@EmbeddedId
private CatAdvId catAdvId;
// bi-directional many-to-one association to DrmAdvertisement
@OneToOne
@JoinColumn(name = "adId", referencedColumnName = "adid", insertable = false, updatable = false)
private DrmAdvertisement drmAdvertisement;
// bi-directional many-to-one association to DrmSubscriber
@OneToOne
@JoinColumn(name = "categoryId", referencedColumnName = "categoryid", insertable = false, updatable = false)
private DrmCategory drmCategory;
}
CatAdvId
@Embeddable
public class CatAdvId implements Serializable {
private static final long serialVersionUID = 1L;
private static final int THIRTYTWO = 32;
private static final int THIRTYTHREE = 32;
private long categoryId;
private long adId;
public CatAdvId()
{
}
public CatAdvId(long categoryId, long adId)
{
this.categoryId = categoryId;
this.adId = adId;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (adId ^ (adId >>> THIRTYTWO));
result = prime * result + (int) (categoryId ^ (categoryId >>> THIRTYTHREE));
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CatAdvId other = (CatAdvId) obj;
if (adId != other.adId)
return false;
if (categoryId != other.categoryId)
return false;
return true;
}
}
您必须映射 DrmAdvertisement 和 DrmCategoryAdvertisement 之间的关系,那么您的查询将是:
SELECT a FROM DrmAdvertisement a where a.adType = :adType and a.drmCategory.categoryId = :categoryid
编辑:
您可以删除映射 DrmCategoryAdvertisement 和 CatAdvId,并在 DrmCategory 中使用 'mappedBy':
@OneToMany(fetch = FetchType.LAZY, mappedBy = "drmCategory")
private Set<DrmAdvertisement> drmAdvertisementSet;