【问题标题】:@Formula not working in hibernate with object@Formula 不能与对象一起在休眠状态下工作
【发布时间】:2014-09-02 05:17:28
【问题描述】:

我有几个状态值的枚举

新、已审核、已发布、待处理、已更新、垃圾邮件、重复、不相关、未发布

我不想将它们用作枚举,因此为此创建了一个实体。为方便起见,我想在实体中保留一列以从枚举初始化状态并将该枚举值转换为状态实体的对象。为此..

我有两个实体。我想引用来自另一个实体的值的列。

基本上我想用公式初始化一个对象。

实体是

@Entity
@Table(name = "event_status")
public class EventStatus {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="eventStatusId")
    private Integer eventStatusId;

    @Enumerated(EnumType.STRING)
    @Column(unique = true,name="eventStatusType")
    private EventStatusType eventStatusType;

    public EventStatus() {
        this(EventStatusType.NEW);
    }

    public EventStatus(EventStatusType eventStatusType) {
        super();
        this.eventStatusType = eventStatusType;
    }

    public Integer getEventStatusId() {
        return eventStatusId;
    }

    public EventStatusType getEventStatusType() {
        return eventStatusType;
    }

    public void setEventStatusId(Integer eventStatusId) {
        this.eventStatusId = eventStatusId;
    }

    public void setEventStatusType(EventStatusType eventStatusType) {
        this.eventStatusType = eventStatusType;
    }
}

我有另一个实体,我在其中引用该实体的对象

@Entity
@Table(name = "event_")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Event implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id_")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Transient
    public EventStatusType eventStatusType = EventStatusType.NEW;

    @ManyToOne(fetch = FetchType.EAGER, targetEntity = EventStatus.class)
    @Formula("select * from event_status where eventStatusId= 1")
    private EventStatus status;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public EventStatus getStatus() {
        System.out.println("Event.getStatus() " + status);
        return status;
    }

    public void setStatus(EventStatus status) {
        System.out.println("Event.setStatus()");
        this.status = status;
    }
}

这没有给出任何异常,但没有初始化这个值。 是否可以使用事件实体中的 eventStatusType 值初始化此 EntityStatus

【问题讨论】:

  • @Formula 必须返回通常会返回 column 的映射。所以在这种情况下,Hibernate 需要获取 status-ID。这应该是@Formula 的结果,而不是选择该对象...
  • 你的意思是我必须将我的 sql 更改为 'select eventStatusId from event_status where eventStatusId= 1'
  • 好吧,不!这无济于事,因为:我们需要的是创建一些智能选择......事实上,我们应该说@Formula(“(1)”)。信不信由你,这对 Hibernate 来说已经足够了。为什么? Hibernate 将采用该值并使用提供的 id 搜索 EventStatus... 有意义吗?你的方法会奏效,但不是我们需要的。我们正在尝试用一些更智能的值替换该列,在 DB 端进行评估...
  • 无法给出异常'java.sql.SQLException:字段'status'没有默认值'
  • @Formula 并不复杂。当没有适当值的列时,它确实可以帮助我们解决问题。我们可以计算它。但问题是:它可能是只读的......

标签: java hibernate jpa


【解决方案1】:

我想根据documentation来解释一下:

5.1.4.1.5. Formula

有时,您希望数据库为您而不是在 JVM 中进行一些计算,您还可以创建某种虚拟列。您可以使用 SQL 片段(又名公式)而不是将属性映射到列。这种属性是只读的(其值由您的公式片段计算)。

@Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()

SQL 片段可以任意复杂,甚至包括子选择。

...

5.1.7.1. Using a foreign key or an association table

...

注意

您可以使用 SQL 片段通过 @JoinColumnOrFormula / @JoinColumnOrformulas 注释模拟物理连接列(就像您可以使用 SQL 片段通过 @Formula 注释模拟属性列一样)。

@Entity
public class Ticket implements Serializable {
    @ManyToOne
    @JoinColumnOrFormula(formula="(firstname + ' ' + lastname)")
    public Person getOwner() {
        return person;
    }
    ...
} 

另外,我们应该使用 insertable = false, updatable = false,因为这样的映射是不可编辑的

【讨论】:

  • 这些公式列是只读的吗?如果是这样,那么在我的情况下它无济于事。我想在创建和持久化时将枚举值更改为 Object
  • 看,从 SQL 的角度考虑。如果计算列...它可以用于获取值。但是没有办法插入那组不可预测的源值......所以公式==只读。抱歉,想帮忙......无论如何享受 Hibernate ;) 很棒的工具
  • 谢谢。如果你能帮忙。你能告诉我管理我的状态枚举的最佳方法吗?实际上我想避免 DB 中的字符串值(重复)。如果我将它们保存在数据库中,那么每次我必须通过从数据库中获取来设置它们。最好的使用方法是什么。
  • 不完全确定我是否理解,因为为什么不能有列 statusId?和标准的多对一映射?那将是我会去的方式...... EventStatus 也应该在数据库中作为一个表。为什么?外键约束。这就是我的经验。我不得不说:喜欢。运行时没问题(与枚举一起工作),数据库也是如此,因为即使没有代码它也是可读的! (外键,事件状态表)。这就是我的方式。
  • 所以最后的结论是这样的。我无法用公式解决这个问题。这个东西我得手动维护。
猜你喜欢
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 2012-09-01
  • 2019-03-28
  • 2011-04-03
  • 1970-01-01
  • 2012-04-28
相关资源
最近更新 更多