【问题标题】:Hibernate @Entity conflict with Spring @Autowired for non-column objectHibernate @Entity 与 Spring @Autowired 冲突,用于非列对象
【发布时间】:2020-03-25 16:20:56
【问题描述】:

我有一个包含项目描述的表格。物品的价格历史可能非常广泛。正是最后一点让我避免使用带有延迟加载的普通一对多 Hibernate 映射。想想价格历史,例如证券交易所的报价,很多历史。

所以我有一个运行良好的缓存,它全部与 Spring 连接,注入 DAO,缓存管理需要查询的内容与它已经知道的内容。

因此,“自然”的事情是能够询问商品的价格历史。这是一些代码,是真实的精简版:

@Entity @Table(name="item")
public class Item {
    @Id
    @Column(name="id")
    private long id;
    @Column(name="name")
    private String name;

    @Autowired
    private PriceCache priceCache;

    /* ...setters, getters for id, name ... */

    public NavigableMap<LocalDateTime,SecurityValue> getPrices(LocalDateTime begTime, LocalDateTime endTime) {
        return priceCache.get(id, begTime, endTime);
    }
}

我的原始版本使用 PriceCache 的所有静态方法;我想切换到使用注入的bean,部分原因是这意味着我可以将缓存重写为接口的实现,这样可以更轻松地为示例中没有的某些位设置单元测试;我可以创建一个测试缓存对象,以任何我需要的方式提供我的价格历史记录,而无需访问数据库。

问题是当 Spring 和 Hibernate 扫描包时,它们似乎在如何处理 @Autowired 字段上发生冲突;为了便于阅读,我得到了以下格式); dbEMF 是我的 EntityManagerFactory:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
   Error creating bean with name 'dbEMF' defined in class path resource [applicationContext.xml]:
     Invocation of init method failed;
   nested exception is javax.persistence.PersistenceException:
     [PersistenceUnit: default] Unable to build Hibernate SessionFactory;
   nested exception is org.hibernate.MappingException:
     Could not determine type for: com.example.cache.PriceCache, at table: item, for columns: [org.hibernate.mapping.Column(priceCache)]

再次,只要我对 PriceCache 使用静态方法,基本代码和缓存工作正常,我在其中“手动”将其创建为单例。将其转换为让 Spring 处理其他地方的创建和注入也可以正常工作。只有当我混合使用 Hibernate 和 Spring 时才会遇到问题。

我还没有尝试过使用外部 XML 文件来进行休眠配置,这可能会解决问题。

有没有办法告诉 Hibernate 这不是列?或者我应该遵循不同的模式来做这种事情,也许是 Item 对象的某种代理?

【问题讨论】:

标签: java spring hibernate autowired


【解决方案1】:

您可以使用@Transient 注释来指示它不应该被持久化到数据库中。

一般来说,我认为如果这是一个实体,它不应该有任何不属于它的自动装配缓存,但这是另一回事

【讨论】:

  • 我想我理解你为什么这么想,这就是我询问不同模式的重点。从商业的角度来看,询问一个项目的价格历史是非常有意义的。该历史属于该项目。但从性能和用例的角度来看,让 Hibernate 直接处理它是“不好的”。
  • 但是hibernate会为你延迟加载曾经被要求的价格历史记录
  • @RolandRoberts 它可能被认为是“价格历史属于项目”,但项目是离散项目还是包含先前价格和其他状态的“项目的连续流动”? Nir Levy 是对的,除了 JPA 注释之外,实体不应包含太多其他内容。该缓存应该注入到服务类中,而不是实体中。
  • @MarcinL,你没有阅读我的信息:-|。有几十万行的价格历史记录,典型的请求只需要几百行。即使使用 Oracle Exadata 数据库,当我让 Hibernate 延迟加载它们时,每个请求也需要几分钟时间。就我而言,这还不够懒惰。这就是为什么 PriceCache 允许按日期时间范围询问的原因。
  • @Kayaman,好的,我会买那个。在某种程度上,缓存是一个服务容器。我已经这样标记了它们,以便正确注入 DAO。有一个返回项目的 ItemCache 服务。一个我得到一个项目,我想询问它的价格历史的某些部分。并不是不属于完整的价格历史记录,只是它是大多数用例的性能瓶颈。
【解决方案2】:

关于下面答案中的讨论。 Hibernate 集合和实体都是代理对象。 也许您可以尝试实现一个自定义 HibernateProxy 来管理您的集合。 根据文档,这似乎是可能的(CustomProxies),但我从未做过检查:https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#entity-proxy

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-12-12
  • 2015-07-23
  • 2019-04-20
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
相关资源
最近更新 更多