问题描述
我使用Cayenne 3.2M1和Postgres 9.0.1来创建数据库。现在我有Cayenne的主键生成的问题,因为我有多个主键的表,并且就我看过Cayenne不能生成更多的每个表一个主键。所以我想要Postgres做这项工作。
我有这个表:
CREATE TABLE telefonocliente
(
cod_cliente integer NOT NULL DEFAULT currval('cliente_serial':: regclass),
cod_telefono integer NOT NULL DEFAULT nextval('telefonocliente_serial':: regclass),
fijo integer,
CONSTRAINT telefonocliente_pkey PRIMARY KEY(cod_cliente,cod_telefono)
)
WITH(
OIDS = FALSE
);
TelefonoCliente telefono = context.newObject(TelefonoCliente.class);
telefono.setFijo(4999000);
context.commitChanges();
这是我得到的错误:
INFO:---事务已开始。
19/11/2013 22:46:17 org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy processSchemaUpdate
INFO:检测到完全或部分模式,跳过表创建
19/11/2013 22:46:17 org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
INFO:SELECT nextval('pk_telefonocliente')
线程main中的异常org.apache.cayenne.CayenneRuntimeException:[v.3.2 M1 Jul 07 2013 16:23:58]在org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:759)
在org.apache.cayenne.access.DataContext提交异常
。 commitChanges(DataContext.java:676)
at org.example.cayenne.Main.main(Main.java:45)
引发者:org.postgresql.util.PSQLException:错误:no existe la relaci ?n«pk_telefonocliente»
位置:16
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl。 processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java: 500)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:254)
在org .apache.cayenne.dba.postgres.PostgresPkGenerator.longPkFromDatabase(PostgresPkGenerator.java:79)
在org.apache.cayenne.dba.JdbcPkGenerator.generatePk(JdbcPkGenerator.java:272)
在org.apache .cayenne.access.DataDomainInsertBucket.createPermIds(DataDomainInsertBucket.java:171)
在org.apache.cayenne.access.DataDomainInsertBucket.appendQueriesInternal(DataDomainInsertBucket.java:76)
在org.apache.cayenne.access .DataDomainSyncBucket.appendQueries(DataDomainSyncBucket.java:78)
at org.apache.cayenne.access.DataDomainFlushAction.preprocess(DataDomainFlushAction.java:188)
at org.apache.cayenne.access.DataDomainFlushAction.flush (DataDomainFlushAction.java:144)
at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:685)
at org.apache.cayenne.access.DataDomain $ 2.transform(DataDomain。 java:651)
at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:712)
at org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:648)
at org.apache.cayenne.access.DataDomain $ DataDomainSyncFilterChain.onSync(DataDomain.java:852)
at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:629)
at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:727)
... 2 more
我一直在尝试关于Cayenne教程生成的列,主键支持的建议,但我似乎总是得到一些错误。
INFO:SELECT nextval('pk_telefonocliente')
线程main中的异常org.apache.cayenne.CayenneRuntimeException :[v.3.2M1 Jul 07 2013 16:23:58]主键自动生成只适用于单个属性。
我想知道如何解决这个问题。
提前感谢
根据注释中的描述,在包含'telefonocliente'只有一个是真正独立的 - cod_telefono。这将是Cayenne将会产生的。在PosgreSQL的情况下,您将需要在DB中的以下序列发生这种情况:
CREATE SEQUENCE pk_telefonocliente INCREMENT 20 START 200;
现在,第二个PK'cod_cliente'从哪里来?因为它也是FK到另一个表,这意味着它是一个依赖PK,并且必须来自一个关系。所以首先你需要在'telefonocliente'和'cliente'之间映射一个多对一的关系。选中telefonocliente侧的To Dep Pk复选框。为您的Java对象生成匹配的ObjRelationship。现在您可以在代码中使用它:
Cliente c = .. //以某种方式获取此对象
TelefonoCliente telefono = context.newObject(TelefonoCliente.class);
telefono.setFijo(4999000);
telefono.setCliente(c); // this line is what will populate'cod_cliente'PK / FK
p>
I'm using Cayenne 3.2M1 and Postgres 9.0.1 to create a database. Right now I'm having problems with the primary key generation of Cayenne since I have tables with more than one primary key and as far as I've read Cayenne cant generate more that one primary key per table. So I want the Postgres to do that work.I have this table:
CREATE TABLE telefonocliente
(
cod_cliente integer NOT NULL DEFAULT currval('cliente_serial'::regclass),
cod_telefono integer NOT NULL DEFAULT nextval('telefonocliente_serial'::regclass),
fijo integer,
CONSTRAINT telefonocliente_pkey PRIMARY KEY (cod_cliente, cod_telefono)
)
WITH (
OIDS=FALSE
);
TelefonoCliente telefono = context.newObject(TelefonoCliente.class);
telefono.setFijo(4999000);
context.commitChanges();
and this is the error I get:
INFO: --- transaction started.
19/11/2013 22:46:17 org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy processSchemaUpdate
INFO: Full or partial schema detected, skipping tables creation
19/11/2013 22:46:17 org.apache.cayenne.log.CommonsJdbcEventLogger logQuery
INFO: SELECT nextval('pk_telefonocliente')
Exception in thread "main" org.apache.cayenne.CayenneRuntimeException: [v.3.2M1 Jul 07 2013 16:23:58] Commit Exception
at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:759)
at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:676)
at org.example.cayenne.Main.main(Main.java:45)
Caused by: org.postgresql.util.PSQLException: ERROR: no existe la relaci?n ≪pk_telefonocliente≫
Position: 16
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:254)
at org.apache.cayenne.dba.postgres.PostgresPkGenerator.longPkFromDatabase(PostgresPkGenerator.java:79)
at org.apache.cayenne.dba.JdbcPkGenerator.generatePk(JdbcPkGenerator.java:272)
at org.apache.cayenne.access.DataDomainInsertBucket.createPermIds(DataDomainInsertBucket.java:171)
at org.apache.cayenne.access.DataDomainInsertBucket.appendQueriesInternal(DataDomainInsertBucket.java:76)
at org.apache.cayenne.access.DataDomainSyncBucket.appendQueries(DataDomainSyncBucket.java:78)
at org.apache.cayenne.access.DataDomainFlushAction.preprocess(DataDomainFlushAction.java:188)
at org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:144)
at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:685)
at org.apache.cayenne.access.DataDomain$2.transform(DataDomain.java:651)
at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:712)
at org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:648)
at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:852)
at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:629)
at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:727)
... 2 more
I've been trying the suggestions on Cayenne tutorial "generated columns", "primary key support" but I seems to always get some error.
INFO: SELECT nextval('pk_telefonocliente')
Exception in thread "main" org.apache.cayenne.CayenneRuntimeException: [v.3.2M1 Jul 07 2013 16:23:58] Primary Key autogeneration only works for a single attribute.
I want to know how to solve this.Thanks in advance
From your description in comments, out of 2 columns comprising the PK of 'telefonocliente', only one is truly independent - 'cod_telefono'. This will be what Cayenne will generate. In case of PosgreSQL, you will need the following sequence in DB for this to happen:
CREATE SEQUENCE pk_telefonocliente INCREMENT 20 START 200;
Now, where does the second PK 'cod_cliente' come from? Since it is also FK to another table, it means it is a "dependent" PK, and must come from a relationship. So first you need to map a many-to-one relationship between 'telefonocliente' and 'cliente'. Check "To Dep Pk" checkbox on the 'telefonocliente' side. Generate a matching ObjRelationship for your Java objects. Now you can use it in your code:
Cliente c = .. // get a hold of this object somehow
TelefonoCliente telefono = context.newObject(TelefonoCliente.class);
telefono.setFijo(4999000);
telefono.setCliente(c); // this line is what will populate 'cod_cliente' PK/FK
That should be it.
这篇关于Cayenne,Postgres:主键生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!