【问题标题】:@OneToMany which is in fact OneToOne / @Formula with Parameters@OneToMany 实际上是带参数的 OneToOne / @Formula
【发布时间】:2015-08-12 10:21:49
【问题描述】:

我有一张桌子 产品 ( ProductId, Name ) 和 ProductPrices(ProductId、市场、价格)

ProductPrices 有一个复合键(ProductId,Market)。对于给定的市场,产品在该市场中的价格为 0..1。

第一种方法@Formula

市场在运行时是已知的,并且可以根据请求进行更改。 在第一次尝试对 ProductEntity 建模时,我使用了 @Formula 注释,如下所示:

@Entity
@Table(...)
public class Product {
@Id
private int ProductId;

private String name;

@Formula("(SELECT TOP 1 Price FROM ProductPrices p WHERE p.ProductId = ProductId  AND p.Market='Berlin')")
private double price;
}

但显然,市场随后是硬编译的,因为注释需要是静态的最终字符串。 [所以没有 @Formula("..." + getCurMarket() ) ]。

第二种方法,@OneToMany

​​>

为价格获取一个单独的实体类,并在产品实体中将它们引用为:

@OneToMany(mappedBy = "product")
private List<Price> price;

getPrice() 中,我总是可以返回第一个条目(永远不会有更多...),如果列表为空,则什么都不返回。

然后我想创建一个谓词/规范以在 ProductService 中使用。示例:

public static Specification<Product> marketEquals(final String market) {
    return new Specification<Product>() {
        @Override
        public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            CriteriaQuery<String> q = cb.createQuery(String.class);
            Root<Price> price = q.from(Price.class);
            return price.get("Market").in("Berlin");
        }
    };
}

但是,这只会导致(我尝试写“市场”、“市场”……)

org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.market' [select generatedAlias0 from ...backend.entities.Product as generatedAlias0 where generatedAlias1.market in (:param0)]

第三种方法,Hibernate/JPA 过滤器

这次我写在产品实体里

 @OneToMany(mappedBy = "product")
    @Filters( {
        @Filter(name="marketFilter", condition="Market = :market")
    } )
  private List<Price> price;

再次,我想在 ProductService 中填写此过滤器,但我无法掌握 CurrentSession。我尝试了Spring-way,添加了@Autowired private SessionFactory sessionFactory;并通过配置

Filter filter =  sessionFactory.getCurrentSession().enableFilter("marketFilter");
filter.setParameter("market", "Berlin" );

但我无法掌握正确的上下文,如org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory

谁能建议如何将数据库模式建模为实体,或者可以指出方法 2 和 3 的可行解决方案?谢谢!

【问题讨论】:

    标签: java spring hibernate jpa spring-boot


    【解决方案1】:

    第二种方法实际上是正确的。尝试更改您的实体和 creteria 查询。

    产品表:

    @Entity
    @Table(...)
    public class Product {
    @Id
    private int ProductId;
    
    private String name;
    
    @OneToMany(mappedBy = "products")
    private List<ProductPrices> ProductPrices;
    }
    

    ProductPrices 表:

    @Entity
    @Table(...)
    public class ProductPrices {
    @Id
    private int ProductPriceId;
    
    private String market;
    
    private double price;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id") //foreign key reference
    private Product products
    }
    

    产品服务:

        CriteriaBuilder cb = em.getCriteriaBuilder();
                    CriteriaQuery<Product> qry = cb.createQuery(Product.class);
                    Root<Product> root = qry.from(Product.class);
                    Join<Product, ProductPrices> price = root.join("ProductPrices");
                    List<Predicate> conditions = new ArrayList<>();
                    conditions.add(cb.equal(price.get("products"), "Berlin"));
    
                    TypedQuery<Product> typedQuery = em.createQuery(qry
                            .select(root)
                            .where(conditions.toArray(new Predicate[] {}))
                            .orderBy(cb.asc(root.get("Berlin")))
                            .distinct(true)
                    );
    
    return typedQuery;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多