JPA规范基于外键的多重连接
JPA Specification multiple join based on foreignkey
我在三个对象之间有以下关系
public class ProductEntity {
@Id
private int id;
@OneToMany(mappedBy = "productEntity",
fetch = FetchType.LAZY)
private List<ProductInfoEntity> productInfoEntityList = new ArrayList<>();
@Column(name = "snippet")
private String snippet;
}
public class ProductInfoEntity {
@Id
private int id;
@ManyToOne
@JoinColumn(name = "product_id")
private ProductEntity productEntity;
@ManyToOne
@JoinColumn(name = "support_language_id")
private SupportLanguageEntity supportLanguageEntity;
}
public class SupportLanguageEntity {
@Id
private int id;
@Column("name")
private String name;
}
这是实际的数据库设计
那么,我想做一个规范查询如下:
select * 来自 product_info
其中 product_id = 1
support_language_id = 2;
我还在规范中使用注释,这意味着我使用 ProductEntity_、ProductInfoEntity_ 等等。
能否提供上述查询规范的完整工作代码?
谢谢大家
select * from product_info where product_id = 1 and support_language_id = 2;
应该如书面那样工作。但唯一有用的是 comment
.
也许您需要所有三个表格中的其余信息?
SELECT pi.comment, -- list the columns you need
p.snippet,
sl.name
FROM product AS p -- table, plus convenient "alias"
JOIN product_info AS pi -- another table
ON p.id = pi.product_info -- explain how the tables are related
JOIN support_language AS sl -- and another
ON pi.support_language_id = sl.id -- how related
WHERE p.snippet = 'abc' -- it is more likely that you will start here
-- The query will figure out the rest.
从那里开始,看看您是否可以解决 JPA 提供的混淆问题。
使用Specification your ProductInfoEntityRepository
have to extend JpaSpecificationExecutor
@Repository
public interface ProductInfoEntityRepository
extends JpaRepository<ProductInfoEntity, Integer>, JpaSpecificationExecutor<ProductInfoEntity> {
}
据我了解,您使用 JPA
元模型。那么
@Autowired
ProductInfoEntityRepository repository;
public List<ProductInfoEntity> findProductInfoEntities(int productId, int languageId) {
return repository.findAll((root, query, builder) -> {
Predicate productPredicate = builder.equal(
root.get(ProductInfoEntity_.productEntity).get(ProductEntity_.id), // or root.get("productEntity").get("id")
productId);
Predicate languagePredicate = builder.equal(
root.get(ProductInfoEntity_.supportLanguageEntity).get(SupportLanguageEntity_.id), // or root.get("supportLanguageEntity").get("id")
languageId);
return builder.and(productPredicate, languagePredicate);
});
}
如果你想让规范可重用,你应该创建实用程序 class 包含两个静态方法 productIdEquals(int)
和 languageIdEquals(int)
。
要组合它们,请使用 Specifications(Spring Data JPA 1.*) or Specification(因为 Spring Data JPA 2.0)
我在三个对象之间有以下关系
public class ProductEntity {
@Id
private int id;
@OneToMany(mappedBy = "productEntity",
fetch = FetchType.LAZY)
private List<ProductInfoEntity> productInfoEntityList = new ArrayList<>();
@Column(name = "snippet")
private String snippet;
}
public class ProductInfoEntity {
@Id
private int id;
@ManyToOne
@JoinColumn(name = "product_id")
private ProductEntity productEntity;
@ManyToOne
@JoinColumn(name = "support_language_id")
private SupportLanguageEntity supportLanguageEntity;
}
public class SupportLanguageEntity {
@Id
private int id;
@Column("name")
private String name;
}
这是实际的数据库设计
那么,我想做一个规范查询如下:
select * 来自 product_info 其中 product_id = 1 support_language_id = 2;
我还在规范中使用注释,这意味着我使用 ProductEntity_、ProductInfoEntity_ 等等。
能否提供上述查询规范的完整工作代码?
谢谢大家
select * from product_info where product_id = 1 and support_language_id = 2;
应该如书面那样工作。但唯一有用的是 comment
.
也许您需要所有三个表格中的其余信息?
SELECT pi.comment, -- list the columns you need
p.snippet,
sl.name
FROM product AS p -- table, plus convenient "alias"
JOIN product_info AS pi -- another table
ON p.id = pi.product_info -- explain how the tables are related
JOIN support_language AS sl -- and another
ON pi.support_language_id = sl.id -- how related
WHERE p.snippet = 'abc' -- it is more likely that you will start here
-- The query will figure out the rest.
从那里开始,看看您是否可以解决 JPA 提供的混淆问题。
使用Specification your ProductInfoEntityRepository
have to extend JpaSpecificationExecutor
@Repository
public interface ProductInfoEntityRepository
extends JpaRepository<ProductInfoEntity, Integer>, JpaSpecificationExecutor<ProductInfoEntity> {
}
据我了解,您使用 JPA
元模型。那么
@Autowired
ProductInfoEntityRepository repository;
public List<ProductInfoEntity> findProductInfoEntities(int productId, int languageId) {
return repository.findAll((root, query, builder) -> {
Predicate productPredicate = builder.equal(
root.get(ProductInfoEntity_.productEntity).get(ProductEntity_.id), // or root.get("productEntity").get("id")
productId);
Predicate languagePredicate = builder.equal(
root.get(ProductInfoEntity_.supportLanguageEntity).get(SupportLanguageEntity_.id), // or root.get("supportLanguageEntity").get("id")
languageId);
return builder.and(productPredicate, languagePredicate);
});
}
如果你想让规范可重用,你应该创建实用程序 class 包含两个静态方法 productIdEquals(int)
和 languageIdEquals(int)
。
要组合它们,请使用 Specifications(Spring Data JPA 1.*) or Specification(因为 Spring Data JPA 2.0)