表sql:在此处输入图像描述
链接创建和测试SQL:https://www.db-fiddle.com/f/9ihygssmwErvhb4ekcUnG5/5
我没有办法将这个sql转换为Spring(方法:toPredicate(Root root, CriteriaQuery
在java中有实体:产品,属性
class Product{
private Long id;
private String name;
@JsonIgnore
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinTable(name = "product_attribute", joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "attribute_id"))
List<Attribute> attributes = new ArrayList<>();
}
class Attribute{
private Long id;
private String name;
private String value;
@JsonIgnore
@ManyToMany(mappedBy = "attributes")
List<Product> products = new ArrayList<>();
}
SQL:
SELECT pa1.product_id
FROM product_attribute pa1,
product_attribute pa2,
product_attribute pa3,
product_attribute pa4
where pa1.attribute_id IN ('A','B')
and pa2.attribute_id IN ('C','D')
and pa3.attribute_id IN ('E','F')
and pa4.attribute_id IN ('G','H')
AND pa2.product_id = pa3.product_id
AND pa1.product_id = pa3.product_id
AND pa1.product_id = pa4.product_id
AND pa2.product_id = pa4.product_id
AND pa3.product_id = pa4.product_id
我尝试过预测方法,但失败了
public class ProductSpecification implements Specification<Product> {
@Override
public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Join<Object, Object> a1Join = root.join( "attributes" );
a1Join.on( criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.equal( a1Join.get( "name" ), "branch" ),
criteriaBuilder.equal( a1Join.get( "value" ), "Acer" )
),
criteriaBuilder.and(
criteriaBuilder.equal( a1Join.get( "name" ), "branch" ),
criteriaBuilder.equal( a1Join.get( "value" ), "Dell" )
)
) );
Join<Object, Object> a2Join = root.join( "attributes" );
a2Join.on( criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.equal( a2Join.get( "name" ), "screen" ),
criteriaBuilder.equal( a2Join.get( "value" ), "13 Inch" )
),
criteriaBuilder.and(
criteriaBuilder.equal( a2Join.get( "name" ), "screen" ),
criteriaBuilder.equal( a2Join.get( "value" ), "15.6 Inch" )
)
) );
Join<Object, Object> a3Join = root.join( "attributes" );
a3Join.on( criteriaBuilder.and(
criteriaBuilder.equal( a3Join.get( "name" ), "need" ),
criteriaBuilder.equal( a3Join.get( "value" ), "gaming" )
) );
Join<Object, Object> a4Join = root.join( "attributes" );
a4Join.on( criteriaBuilder.and(
criteriaBuilder.equal( a4Join.get( "name" ), "memory" ),
criteriaBuilder.equal( a4Join.get( "value" ), "32 G" )
) );
query.distinct(true);
List<Predicate> predicates = new ArrayList<>();
predicates.add(root.in(a1Join,a2Join,a3Join,a4Join));
return builder.and(predicates.toArray(new Predicate[0]));
}
}
结果日志:
Hibernate: select distinct product0_.id as id1_7_, product0_.discount as discount2_7_, product0_.long_description as long_des3_7_, product0_.name as name4_7_, product0_.price as price5_7_, product0_.promotion as promotio6_7_, product0_.quantity as quantity7_7_, product0_.short_description as short_de8_7_, product0_.status as status9_7_, product0_.summary as summary10_7_, product0_.view as view11_7_ from product product0_ inner
join
(product_attribute attributes1_ inner join attribute attribute2_ on attributes1_.attribute_id=attribute2_.id) on product0_.id=attributes1_.product_id and (attribute2_.name=? and attribute2_.value=?) inner join (product_attribute attributes3_ inner join attribute attribute4_ on attributes3_.attribute_id=attribute4_.id) on product0_.id=attributes3_.product_id and (attribute4_.name=? and attribute4_.value=?) inner join (product_attribute attributes5_ inner join attribute attribute6_ on attributes5_.attribute_id=attribute6_.id) on product0_.id=attributes5_.product_id and (attribute6_.name=? and attribute6_.value=?) inner join (product_attribute attributes7_ inner join attribute attribute8_ on attributes7_.attribute_id=attribute8_.id) on product0_.id=attributes7_.product_id and (attribute8_.name=? and attribute8_.value=?) where product0_.id in (attribute2_.id , attribute4_.id , attribute6_.id , attribute8_.id) limit ?
问题在于,您使用的是@manytomy
,这意味着您实际上无法作为一个实体访问桥接表。要编写准确的查询,需要使用桥实体更改映射。参见Hibernate ORM文档中的示例172.双向多对多链接实体。
映射将更改为:
class Product{
private Long id;
private String name;
...
@OneToMany(
mappedBy = "product",
cascade = CascadeType.ALL,
orphanRemoval = true
)
List<ProductAttribute> attributes = new ArrayList<>();
}
@Entity(name = "ProductAttribute")
@Table(name = "product_attribute")
public static class ProductAttribute implements Serializable {
@Id
@ManyToOne
private Product product;
@Id
@ManyToOne
private Attribute attribute;
}
class Attribute{
...
@OneToMany(
mappedBy = "attribute",
cascade = CascadeType.ALL,
orphanRemoval = true
)
List<ProductAttribute> products = new ArrayList<>();
}
现在,您可以编写条件:
CriteriaBuilder criteriaBuilder = ormFactory.getCriteriaBuilder();
CriteriaQuery<Product> criteria = criteriaBuilder.createQuery( Product.class );
Root<Product> root = criteria.from( Product.class );
Join<Object, Object> a1Join = root.join( "attributes" );
Join<Object, Object> a2Join = root.join( "attributes" );
Join<Object, Object> a3Join = root.join( "attributes" );
Join<Object, Object> a4Join = root.join( "attributes" );
Predicate predicate = builder.and(
a1Join.get( "attribute" ).in('A', 'B'),
a2Join.get( "attribute" ).in('C', 'D'),
a3Join.get( "attribute" ).in('E', 'F'),
a4Join.get( "attribute" ).in('G', 'H')
);
criteria.where(predicate);
也就是说,可以创建一个使用连接返回相同结果的条件。我已将您提供的测试sql查询转换为标准。这不是相同的查询,但应该会给你相同的结果(我已经使用Hibernate ORM测试过了):
CriteriaBuilder criteriaBuilder = ormFactory.getCriteriaBuilder();
CriteriaQuery<Product> criteria = criteriaBuilder.createQuery( Product.class );
Root<Product> root = criteria.from( Product.class );
criteria.select( root );
criteria.distinct( true );
Join<Object, Object> a1Join = root.join( "attributes" );
a1Join.on( criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.equal( a1Join.get( "name" ), "branch" ),
criteriaBuilder.equal( a1Join.get( "value" ), "Acer" )
),
criteriaBuilder.and(
criteriaBuilder.equal( a1Join.get( "name" ), "branch" ),
criteriaBuilder.equal( a1Join.get( "value" ), "Dell" )
)
) );
Join<Object, Object> a2Join = root.join( "attributes" );
a2Join.on( criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.equal( a2Join.get( "name" ), "screen" ),
criteriaBuilder.equal( a2Join.get( "value" ), "13 Inch" )
),
criteriaBuilder.and(
criteriaBuilder.equal( a2Join.get( "name" ), "screen" ),
criteriaBuilder.equal( a2Join.get( "value" ), "15.6 Inch" )
)
) );
Join<Object, Object> a3Join = root.join( "attributes" );
a3Join.on( criteriaBuilder.and(
criteriaBuilder.equal( a3Join.get( "name" ), "need" ),
criteriaBuilder.equal( a3Join.get( "value" ), "gaming" )
) );
Join<Object, Object> a4Join = root.join( "attributes" );
a4Join.on( criteriaBuilder.and(
criteriaBuilder.equal( a4Join.get( "name" ), "memory" ),
criteriaBuilder.equal( a4Join.get( "value" ), "32 G" )
) );
try (Session session = ormFactory.openSession()) {
List<Product> resultList = session.createQuery( criteria ).getResultList();
System.out.println( resultList );
}
但是您需要更改方法toPredicate
的签名:
public void toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Join<Object, Object> a1Join = root.join( "attributes" );
... // The same as in the example above
Join<Object, Object> a4Join = root.join( "attributes" );
a4Join.on( ... );
}
你可以像这样使用这个方法:
CriteriaBuilder criteriaBuilder = ...
CriteriaQuery<Product> query = ...
Root<Product> root = criteria.from( Product.class );
specification.toPredicate(root, query, criteriaBuilder);
// Now you can run the query and it will work
问题内容: 我没主意了。现在,我有一天在Google上进行了谷歌搜索,但仍然找不到我的问题的任何有用答案。 到目前为止,我一直尝试使用原始SQL,但是没有运气。 使用此原始SQL查询时,返回的结果为零,但是在其中运行相同的查询时,返回正确的结果。 我进一步发现,将查询打印到终端时,它不能正确处理该子句。 打印时我的查询如下所示: 如何将此SQL查询转换为SQLAlchemy 我的桌子看起来像这样:
我已将此JSON转换为Hashmap http://www.mocky.io/v2/5d0dc72d3400008c00ca4a62 我有嵌套的Hashmap,我想把它转换成ArrayList 我想从获取所有数据并添加到列表中。我还希望hashmap的密钥也将作为指南导入列表中。 这是银行舱 这是银行名单课程 我试过的 但我不明白为什么会有例外 如果可以的话,请给我推荐其他算法
我有一个相当大的系统,它的规范是由子实体上的几个方法构建的。所以我有一个用户,他有一个宠物木偶,就像这个问题一样。我的关系是双向的,所以Pet在用户上也有多对一的关系,我正在努力将子实体上的规范转换为应用于父实体。 我查找的大多数问题都显示了如何在不同的实体上应用规范,或者在规范执行后获得不同的实体。这不是我想要的。 我试着写一个这样的方法: 但我不知道如何编写它(我尝试过使用Join,但没能“告
我需要使用jolt spec在JSON中将(多个)键转换为值,将值转换为键。做这件事的正确规范应该是什么? 输入: 所需输出:
问题内容: 我正在做这个 它给了我这个 但是我想要这个 请帮忙。 问题答案: 首先将其转换为十进制, SQLFiddle演示
问题内容: 我有一个应用程序,该应用程序使用Jackson将我的复杂对象编组为JSON,从而在DynamoDB中存储一些数据。 例如,我要编组的对象可能如下所示: SomeObject可能看起来像这样: 和SomeOtherObject可能看起来像这样: 可以很好地将对象整理成问题并将其作为JSON字符串存储在数据库中。 当需要从DynamoDB检索数据时,Jackson会自动检索JSON并将其转