Cayenne, Postgres: генерация первичного ключа

Я использую 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: --- 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

Я пробовал предложения по учебнику Cayenne «сгенерированные столбцы», «поддержка первичного ключа», но, кажется, всегда получаю какую-то ошибку.

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.

Я хочу знать, как это решить. заранее спасибо


person Vanessa    schedule 20.11.2013    source источник
comment
Cayenne, безусловно, поддерживает таблицы с более чем одним столбцом PK. Но чтобы ответить на ваш вопрос, не могли бы вы объяснить, что означают «cod_cliente» и «cod_telefono» в вашей схеме? Это действительно сгенерированные последовательности или они также являются внешними ключами к некоторым другим таблицам?   -  person andrus_a    schedule 20.11.2013
comment
У меня есть две таблицы cliente и telefonoCliente. cliente имеет один ПК «cod_cliente». telefonocliente PK — это 'cod_telefonocliente, cod_cliente': ОГРАНИЧЕНИЕ pk_telefonocliente ПЕРВИЧНЫЙ КЛЮЧ (cod_cliente, cod_telefono), ОГРАНИЧЕНИЕ fk_telefono_relations_cliente FOREIGN KEY (cod_cliente) REFERENCES cliente (cod_cliente) MATCH SIMPLE   -  person Vanessa    schedule 21.11.2013
comment
так это сработало с ответом ниже?   -  person andrus_a    schedule 25.11.2013
comment
Нет, это не так. Мой учитель сказал, что я должен создать метод в java, который обрабатывает последовательности. Я не мог этого сделать, поэтому я отказываюсь от кратных ПК.   -  person Vanessa    schedule 26.11.2013


Ответы (2)


Судя по вашему описанию в комментариях, из 2-х столбцов, составляющих ПК «telefonocliente», только один действительно независим — «cod_telefono». Это будет то, что будет генерировать Cayenne. В случае PosgreSQL вам понадобится следующая последовательность в БД, чтобы это произошло:

CREATE SEQUENCE pk_telefonocliente INCREMENT 20 START 200;

Итак, откуда взялся второй ПК «cod_cliente»? Поскольку это также FK для другой таблицы, это означает, что это «зависимый» PK и должен исходить из отношения. Итак, сначала вам нужно сопоставить отношение «многие к одному» между «телефоноклиенте» и «клиентом». Установите флажок «To Dep Pk» на стороне «telefonociente». Создайте соответствующий ObjRelationship для ваших объектов Java. Теперь вы можете использовать его в своем коде:

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

Это должно быть так.

person andrus_a    schedule 21.11.2013
comment
Привет @andrus_a Я прочитал в официальном документе следующее предложение: вы должны выбрать отношения, идущие в направлении от главного к зависимому, и установить флажок To Dep PK для этого отношения. Тогда я думаю, что cliente - это мазер, потому что telefonocliente не может существовать без него (см. cod_cliente PK). Поэтому я подумал, что должен проверить зависимый флаг PK для отношения, которое находится в определении DbEntity cliente. Где я не прав? - person Andrea Borgogelli Avveduti; 20.02.2017

Первичный ключ может быть только один на таблицу! В вашем случае вы создаете первичный ключ для двух столбцов, это правильно, он определен в стандарте SQL, и Postgres его хорошо поддерживает.

Однако в документации Cayenne нет:

Cayenne поддерживает автоматическое создание PK только для одного столбца в таблице.

см. http://cayenne.apache.org/docs/3.0/primary-key-generation.html внизу страницы.

Вероятно, они могут исправить это в более новой версии или вы можете оставить запрос сообществу Cayenne.

person Martin Strejc    schedule 20.11.2013