使用注释映射默认列值

发布于 2024-09-19 00:29:15 字数 2523 浏览 7 评论 0原文

@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")
}
@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 + "]";
    }

}

I'm expecting the value '15-JUL-1980' to be inserted for each row IF I DONOT set its value.

But its not working as expected. Am I doing anything wrong here?

For some reasons, I want to set the default value at the application and Not at the database.

UPDATE:

Initially i tried without 'insertable = false' only.

As a newbie, I was trying different options and had kept that option.

Here is the test case which I'm running:

@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);
    }

and the output it has produced:

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]

Table:

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")
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在夏天 2024-09-26 00:29:16

如果我没有设置值“15-JUL-1980”,则希望为每行插入该值。

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

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

什么不能完全工作?你能显示该表的 DDL 脚本吗?到底执行了什么 DML INSERT 语句? Oracle 是否正确设置了默认值?插入后不把它放回实体中吗?什么时候会失败?

以防万一,您是否缺少 creationTime 上的 Temporal 注释?根据 JPA 1.0 规范:

9.1.20 时间注释

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

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

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


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

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

因此,在您的情况下,我可能会使用生命周期回调并在 PrePersist 期间设置日期 if null

@Entity
public class Account {
    ...

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

}

参考

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

I'm expecting the value '15-JUL-1980' to be inserted for each row IF I DO NOT set its value.

Actually, the creationTime will never be part of the SQL INSERT statement even if you set a value because of the insertable = false.

But its not working as expected. Am I doing anything wrong here?

What is not working exactly? Can you show the DDL script for the table? What DML INSERT statement is performed exactly? Does Oracle set the default appropriately? Don't you get it back in the entity after the insert? When does it fail?

Just in case, aren't you missing a Temporal annotation on the creationTime? According to the JPA 1.0 spec:

9.1.20 Temporal Annotation

The Temporal annotation must be specified for persistent fields or properties of type
java.util.Date and java.util.Calendar. It may only be specified for fields or properties of these types.

I would add a @Temporal(TemporalType.DATE).

Not sure this will solve the issue though but answering the above questions might help to diagnose the issue.


I want Hibernate to set the default value when ever I'm trying to insert. The table i've shown is a dummy table which I created for testing/learnig purpose. The Original table is a legacy one and it does not have the 'DEFAULT' attribute set. Sorry about the confusion.

The columnDefinition element of the Column annotation is used to specify the SQL fragment that is used when generating the DDL for the column, that's all. If you don't use the JPA provider to generate the DDL and if your table doesn't have any DEFAULT defined, nothing will happen.

So in your case, I would probably use a lifecyle callback and set the date if null during PrePersist:

@Entity
public class Account {
    ...

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

}

Reference

  • JPA 1.0 Specification
    • Section 3.5.1 "Lifecycle Callback Methods"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文