java - @OneToMany 实际上是带有参数的 OneToOne/@Formula

标签 java spring hibernate jpa spring-boot

我有一张 table 产品(ProductId、Name)和 产品价格(产品 ID、市场、价格)

ProductPrices有一个compositeKey(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 提供可行的解决方案?谢谢!

最佳答案

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

产品表:

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

private String name;

@OneToMany(mappedBy = "products")
private List<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;

关于java - @OneToMany 实际上是带有参数的 OneToOne/@Formula,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31962439/

相关文章:

java - Hibernate @OrderBy 注释和 MySQLSyntaxErrorException

javascript - jqgrid海量数据加载问题

java - 使用 FactoryBean 创建泛型实例时,Spring 自动接线无法泛型

Spring 3.0 RmiProxyFactoryBean : how to change serviceUrl at runtime?

java - 使用 Open Session In View 时事务传播如何工作?

java - Spring data JPA中findBy和findOneBy的区别

java - 正则表达式,通过验证计算其中的 CRC

java - 如何检测 SWT Table 的滚动条可见性变化

java - 为网站创建 API

java - Spring MVC JSP表单错误