【问题标题】:map default column value with annotations使用注释映射默认列值
【发布时间】:2010-09-12 17:41:06
【问题描述】:
@Entity
@Table(name = "J_CNTRY")
public class CountryEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "myTableGenerator")
    @TableGenerator(name = "myTableGenerator", allocationSize = 5, pkColumnName = "pkName", valueColumnName = "pkValue", table = "j_cntry_pk_table")
    private Long id;

    private String country;

    @Generated(GenerationTime.INSERT)
    @Column(name = "CREATION_TIME", columnDefinition = "DATE default '15-JUL-1980'", insertable = false)
    private Date creationTime;

    public CountryEntity() {
    }

    public Long getId() {
        return id;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(final String country) {
        this.country = country;
    }

    public Date getCreationTime() {
        return creationTime;
    }

    @Override
    public String toString() {
        return "Country [id=" + id + ", country=" + country + ", creationTime="
                + creationTime + "]";
    }

}

如果我不设置其值,我希望为每一行插入值“15-JUL-1980”。

但它没有按预期工作。我在这里做错了吗?

由于某些原因,我想在应用程序中设置默认值,而不是在数据库中。

更新

最初我只尝试不使用 'insertable = false'。

作为一个新手,我尝试了不同的选择并保留了那个选择。

这是我正在运行的测试用例:

@Test
    public void testCreateCountry4() {
        final CountryEntity a1 = new CountryEntity();
        a1.setCountry("Xxxx");
        final Session currentSession = sessionFactory.getCurrentSession();
        final Long savedId = (Long) currentSession.save(a1);
        System.out.println("Saved with ID = " + savedId);
        currentSession.flush();
        System.out.println("Saved object = " + a1);
        assertNotNull(savedId);
    }

以及它产生的输出:

Saved with ID = 85
Hibernate: 
    /* insert entities.CountryEntity
        */ insert 
        into
            J_CNTRY
            (country, id) 
        values
            (?, ?)
Hibernate: 
    /* get generated state entities.CountryEntity */ select
        countryent_.CREATION_TIME as CREATION3_2_ 
    from
        J_CNTRY countryent_ 
    where
        countryent_.id=?
Saved object = Country [id=85, country=Xxxx, creationTime=null]

表:

CREATE TABLE "FOO"."J_CNTRY" 
   (    "ID" VARCHAR2(255 BYTE) NOT NULL, 
    "COUNTRY" VARCHAR2(255 BYTE), 
    "CREATION_TIME" DATE, 
     CONSTRAINT "J_CNTRY_PK" PRIMARY KEY ("ID")
}

【问题讨论】:

  • 其实问题出在列定义"CREATION_TIME" DATE DEFAULT NULL,对吧?这个表是由 Hibernate 生成的吗?从头开始?
  • @Pascal:我是 Hibernate 的新手。我希望 Hibernate 在我尝试插入时设置默认值。我展示的表格是我为测试/学习目的而创建的虚拟表格。原始表是旧表,它没有设置“默认”属性。很抱歉造成混乱。

标签: hibernate annotations default-value oracle9i hibernate-annotations


【解决方案1】:

如果我不设置它的值,我希望为每一行插入值“15-JUL-1980”。

实际上,creationTime 永远不会成为 SQL INSERT 语句的一部分,即使您因为 insertable = false 而设置了一个值。

但它没有按预期工作。我在这里做错了吗?

确实有什么问题?你能显示表格的 DDL 脚本吗?究竟执行了什么 DML INSERT 语句? Oracle 是否适当地设置了默认值?插入后你不把它放回实体中吗?什么时候失败?

以防万一,您不会在creationTime 上缺少Temporal 注释吗?根据 JPA 1.0 规范:

9.1.20 时间注释

Temporal 注释必须为持久字段或类型的属性指定 java.util.Datejava.util.Calendar。只能为这些类型的字段或属性指定。

我会添加一个@Temporal(TemporalType.DATE)

虽然不确定这是否能解决问题,但回答上述问题可能有助于诊断问题。


我希望 Hibernate 在我尝试插入时设置默认值。我展示的表格是我为测试/学习目的而创建的虚拟表格。原始表是旧表,它没有设置“默认”属性。很抱歉造成混乱。

Column 注释的columnDefinition 元素用于指定在为列生成 DDL 时使用的 SQL 片段,仅此而已。如果您不使用 JPA 提供程序来生成 DDL,并且您的表没有定义任何 DEFAULT,则不会发生任何事情。

所以在你的情况下,如果nullPrePersist 期间,我可能会使用生命周期回调并设置日期:

@Entity
public class Account {
    ...

    @PrePersist
    protected void setCreationDateIfRequired() {
        if (getCreationDate() == null) {
            setCreationDate(...);
        }
    }

}

参考

  • JPA 1.0 规范
    • 第 3.5.1 节“生命周期回调方法”

【讨论】:

    猜你喜欢
    • 2018-12-21
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多