管理PK代我:如何與卡宴4.0 + 9.4的PostgreSQL
- 的PostgreSQL 9.4
- 阿帕奇卡宴4.0.M3
它由一個簡單的表格 「PROBA」 A模式:
CREATE TABLE PROBA( ID BIGINT NOT NULL, 值字符改變(255), 約束proba_pkey PRIMARY KEY(ID) )
一個簡單的Main方法:
public static void main(String[] args) { ServerRuntime runtime = ServerRuntimeBuilder.builder() .addConfig("cayenne-project.xml") .build(); ObjectContext ctx = runtime.newContext(); CayenneDataObject newObject = new CayenneDataObject(); newObject.writeProperty("value", "proba1"); ctx.registerNewObject(newObject); ctx.commitChanges(); }
一個簡單的辣椒-project.xml中:
<?xml version="1.0" encoding="utf-8"?> <domain project-version="7"> <map name="datamap"/> <node name="datanode" factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory" schema-update-strategy="org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy"> <map-ref name="datamap"/> <data-source> .... </data-source> </node> </domain>
一個簡單datamap.map.xml(手maded):
<?xml version="1.0" encoding="utf-8"?> <data-map xmlns="http://cayenne.apache.org/schema/7/modelMap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd" project-version="7"> <property name="defaultPackage" value="ru.xxx"/> <property name="defaultSchema" value="public"/> <db-entity name="proba" schema="public"> <db-attribute name="id" type="BIGINT" isPrimaryKey="true" isGenerated="false" length="19"/> <db-attribute name="value" type="VARCHAR" length="255"/> </db-entity> <obj-entity name="Proba" dbEntityName="proba"> <obj-attribute name="value" type="java.lang.String" db-attribute-path="value"/> </obj-entity> </data-map>
嘗試它,我得到了以下輸出:
INFO: --- transaction started.
Nov 15, 2016 5:06:26 PM org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
INFO: SELECT nextval('public.pk_proba')
Exception in thread "main" org.apache.cayenne.CayenneRuntimeException: [v.4.0.M3 Feb 08 2016 16:38:05] Commit Exception
at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:776)
at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:693)
at com.echelon.proba.cayenne.Main.main(Main.java:27)
Caused by: org.postgresql.util.PSQLException: ERROR: relation "public.pk_proba" does not exist
Position: 16
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2458)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2158)
因此,卡宴期望一個名爲pk_proba的序列。爲什麼?我不是說要生成它。我沒有在我的模式中,也沒有在Cayenne映射中提到任何postgresql序列。
所以,我有兩個問題:
- 我怎樣才能抑制卡宴嘗試生成的ID,讓卡宴快速失敗,如果在提交時提供了具體的實體沒有身份?
- 我可以自定義一種方式,讓Cayenne管理我的項目中的PK自動生成(最好的解決方案是不涉及Cayenne Modeller的解決方案)?
謝謝安德魯斯提供的解決方案適用於我,至少對於案例2(自定義ID生成管理)。 – skapral
對於案例1(快速失蹤身份失敗),我個人預計會在db-attribute或obj-attribute上有一些標誌(更令我驚訝的是,有一個名爲isGenerated,但沒有區別)。回答你的問題(爲什麼?畢竟你確實希望你的插入成功) - 如果我的密鑰由另一方管理:在數據庫之外的地方怎麼辦?無論如何 - 在JPA中,只需不加@GeneratedValue註解就可以實現 - 爲什麼它在Cayenne中非常重要? – skapral
生成==自動增量。它確實有所作爲,但只適用於PostgreSQL的M4。 –