2010-12-22 77 views
14

避免向數據庫表中插入'null'值,從JPA2開始,到目前爲止感覺非常舒適。但是,對於具有默認值的NON NULL數據庫字段,使用空屬性值持久化實體時遇到問題。通過JPA

我想能夠離開實體屬性爲空,並讓數據庫插入默認值。

我目前的設置是openJPA和PostgreSQL。

我有此VERSION數據庫表(Vorgabewert =默認值):

 

    Spalte  |    Typ    |   Attribute 
----------------+-----------------------------+---------------------------- 
status_  | smallint     | not null Vorgabewert 0 
time_   | timestamp without time zone | not null 
system_time | timestamp without time zone | not null Vorgabewert now() 
version  | character varying(20)  | not null 
activationtime | timestamp without time zone | 
importtime  | timestamp without time zone | 
 

我具有由XML配置的實體(爪哇DTO),其映射數據庫字段(除了 '狀態')。

我希望我可以插入一個沒有system_time集的實體,並且期望數據庫將當前時間填充爲默認值。

JPA構造下面的SQL查詢:

INSERT INTO public.version (version, activationtime, importtime, system_time, time_) VALUES (?, ?, ?, ?, ?) [params=?, ?, ?, ?, ?] 

和Postgres與反應:

FEHLER: NULL-Wert in Spalte »system_time« verletzt Not-Null-Constraint(對不起,德語,但這個消息意味着非空約束違反了「SYSTEM_TIME」) 。

那麼我該怎麼辦?這是一個JPA或數據庫問題。 我可以將JPA配置爲從INSERT SQL語句中排除空屬性嗎?

我希望能夠在我的實體中設置'system_time'或讓它爲'null',並讓數據庫將默認值設置爲'null'。

歡迎任何幫助!

Regads 克勞斯

回答

14

我不會依賴與JPA結合使用數據庫中的默認值。在插入之後,您將不得不讀取實體,否則實體狀態和db狀態之間不匹配。

在這裏選擇實用的方法並初始化java中的所有值。從來沒有聽說過一種方法來告訴JPA/Hibernate在插入/更新中省略空值。

-1

只需從INSERT語句中的列離開了SYSTEM_TIME。

+0

由JPA EntityManager的持續的實體(javax.persistence.EntityManager.persist(對象))時產生的INSERT statment。如何將JPA配置爲在空列時省略該列? – FrVaBe 2010-12-22 12:03:02

+0

不確定JPA,但Hibernate支持註釋「dynamicInsert = true,dynamicUpdate = true」,它不會發送任何未更改的行。 – 2010-12-22 13:04:49

+0

Hibernate還在屬性映射上支持「insert ='false'」和「update ='false'」,以省略生成的靜態插入/更新SQL中的某些列。映射「insert ='false'generated ='insert'」在這裏可能是合適的(不知道如何將其轉換爲註釋配置)。 – araqnid 2010-12-23 11:11:05

2

來自文檔:columnDefinition:爲列生成DDL時使用的SQL片段。

通過使用columnDefinition,您可以根據需要指定約束。

@Column(name = 「COLUMN_NAME」,columnDefinition = 「DATE DEFAULT CURRENT_DATE」,表= 「TABLE_NAME」)

其他你可以嘗試在實體本身初始化場擺脫這一點。

@Column(name = "somedate", nullable = false) 
private Date someDate = new Date(); 

所以在默認情況下,當前日期將被插入,如果你沒有設置它。

+1

正如你所引用的那樣,這個定義僅在生成列的DDL時使用(用於創建表)。因此,在運行應用程序時,它對SQL語句中的空值沒有任何影響(當試圖在此列中插入NULL時,仍然會出現違例)。這同樣發生在普通SQL上,因此我正在尋找JPA中的配置方式,以便在生成的(INSERT)SQL語句爲空時排除列。 – FrVaBe 2010-12-22 12:45:32

17

使用註釋

@Column(insertable = false) 

將防止值在SQL的產生。

-1

我不知道有什麼辦法可以在JPA中做到這一點。

但是,您可以向數據庫添加一個觸發器,該觸發器捕獲將NULL插入問題列的嘗試,並重寫插入以插入默認值?實質上,您將默認生成行爲完全移到數據庫中,而不是在JPA和數據庫之間進行拆分。

但是,正如伯特在他的回答中指出的那樣,這會使對象和數據庫不一致,這幾乎肯定是一個糟糕的想法。

-1

,你可以用這樣的方式:

@JoinColumn(name = "team_id", nullable = false) 

使用這種方式,JPA將檢查NULL值。

3

在Annotation @Column把屬性附加傷害插入假像這樣:

 
`@Column(name="system_time", insertable = false)` 

,或者您需要檢查時,該值爲NULL,則使觸發前表的INSERT 。

0

我用這個(針對Oracle數據庫):

@Temporal(TemporalType.TIMESTAMP) 
@Column(name="CREATION_TIME", 
     columnDefinition="TIMESTAMP DEFAULT SYSTIMESTAMP", 
     nullable=false, 
     insertable=false, 
     updatable=false) 
private Date creationTime;