Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Составной ИД в ентити, ребус, крохсворд, загадка природы / 10 сообщений из 10, страница 1 из 1
03.04.2012, 12:35:38
    #37736121
AndreyDmt
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Приветсвую!
Вчера к концу дня заимел заморочку, думал дело житейское -
конец понедельника. Ан нет, не рассосалось.
Голову сломал, явно мой глюк, но найти не могу, спасайте!
(Все исходные в конце приведу - пока плач Ярославны)
Суть беды: периодически возникает необходимость в Entity
описывать составной первичный ключ. Не злоупотребляю, но бывает.
В проекте штуки 3-4 есть таких, проблем не доставляют, всё работает.
Вчера затеял изменение, в том числе поменял в одном из ентити простой
ключ на составной. МетОда под копирку, кнтрл Ц - кнтрл В.
Компилю, деплою - на правленном ентити выскакивает ошибка от
хибернейта: пропущена колонка. Смотрю, чешу репу. А с чего ей
быть - оно же через @Transient описано. Комментирую, деплою, результат -
не находится следующее поле, по алфавиту как оказалось(уже реальное).
Причём не находит имя не то, что в @Column(name="") указано,
а имя поля класса (ну не совпадают они у меня). Меняю поле в классе
на то, как оно пишется в таблице - признаёт. Но ругань на следующее поле.
Причём для меня стало открытием, что хибернейту (или кому?) по барабану
на геттеры-сеттеры: он явно проверяет приват поле (как?) и на него
рурается, или признаёт. Ибо я имя полю поменял, а геттеры-сеттеры остались
прежние, забылся. Так ить сработало! Ушла ошибка дальше. Так и должно быть?
Вобщем вывод сделал следующий: в отдельно взятом ентити перестали
работать (опознаваться) аннотации. Понял, что бред, пошёл бороться дальше.
Начал сравнивать побайтно тексты классов, которые работают, и сломанного -
отличий не нашёл. Перечитал туториал по j2ee5 - вроде всё правильно у меня,
всё по буквам. Создал новую тестовую табличку, с нуля написал ентити,
класс составного ключа - ошибка. Но блин, соседние ентити ж работают!
Смотрю по списку в логах - нормално их хбернейт проходит, не жалуется.
Вообщем или мозги в отгуле, или глаз замылился. Поспособствуйте прозрению плиз!

Театр действий:
windowsXP
jdk-1.6.31
Jboss-5.1, seam-2.2.2
Eclipse 3.7.2 + JbossTools 3.3
БД - Oracle10.2
Исходники по тестовой таблице, классам:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE TABLE A$_CONTEXTDATA (
  APPLICATION_ID     NUMBER(20)                 NOT NULL,
  CONTEXTCLASS_NAME  VARCHAR2(100 CHAR)         NOT NULL,
  HELP_CONTEXT       VARCHAR2(200 CHAR)
);

CREATE UNIQUE INDEX A$_CONTEXTDATA_PK ON A$_CONTEXTDATA
(APPLICATION_ID, CONTEXTCLASS_NAME);

ALTER TABLE A$_CONTEXTDATA ADD (
  CONSTRAINT A$_CONTEXTDATA_PK
 PRIMARY KEY
 (APPLICATION_ID, CONTEXTCLASS_NAME));


Первичный ключ:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
package org.kronacommon.app.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public final class AaaContextDataKey implements Serializable {

	private static final long serialVersionUID = 1493537710517406682L;

	public AaaContextDataKey() {
	}

	// На это ругается, если поменять на application_id, не меняя
	// get - set, то поле считается правильно оформленным
	private Long appId;

	@Column(name = "APPLICATION_ID")
	public Long getAppId() {
		return this.appId;
	}

	public void setAppId(Long appId) {
		this.appId = appId;
	}

	private String contCN;

	@Column(name = "CONTEXTCLASS_NAME")
	public String getContCN() {
		return this.contCN;
	}

	public void setContCN(String contCN) {
		this.contCN = contCN;
	}

	@Override
	public boolean equals(Object otherKey) {
		if (this == otherKey) return true;
		if (otherKey == null) return false;
		if (!(otherKey instanceof AaaContextDataKey)) return false;
		AaaContextDataKey other = (AaaContextDataKey) otherKey;
		if ((this.appId == null) & (other.appId != null)) return false;
		if ((this.appId != null) & (other.appId == null)) return false;
		if ((this.contCN == null) & (other.contCN != null)) return false;
		if ((this.contCN != null) & (other.contCN == null)) return false;
		if ((this.appId == null) & (other.appId == null) & (this.contCN == null)
				& (other.contCN == null)) return true;
		if ((this.appId.equals(other.appId)) && (this.contCN.equals(other.contCN))) return true;
		return false;
	}

	@Override
	public int hashCode() {
		return ((this.appId == null ? 0 : this.appId.hashCode()) ^ (this.contCN == null ? 0
				: this.contCN.hashCode()));
	}

	@Override
	public String toString() {
		return "" + this.appId.toString() + "." + this.contCN;
	}
}


Сам ентити:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
package org.kronacommon.app.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "A$_CONTEXTDATA")
public class AaaContextDataEntity implements Serializable {

	private static final long serialVersionUID = 8244148633373180589L;

	public AaaContextDataEntity() {

	}

	//
	@EmbeddedId
	private AaaContextDataKey contextDataKey;

	public AaaContextDataKey getContextDataKey() {
		return this.contextDataKey;
	}

	public void setContextDataKey(AaaContextDataKey contextDataKey) {
		this.contextDataKey = contextDataKey;
	}
	
	// Правлю поля в классе первичного ключа, ругань перекидывается сюда
	private String helpContext;

	@Column(name = "HELP_CONTEXT", length = 200, unique = false, nullable = true)
	public String getHelpContext() {
		return this.helpContext;
	}

	public void setHelpContext(String helpcontext) {
		this.helpContext = helpcontext;
	}
}


Сообщение об ошибке:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
2012-04-03 14:01:01,984 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (HDScanner) table found: KRONAV2.A$_CONTEXTDATA
2012-04-03 14:01:01,984 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (HDScanner) columns: [help_context, contextclass_name, application_id]
2012-04-03 14:01:01,984 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] (HDScanner) Error installing to Start: name=persistence.unit:unitName=kronav2mear.ear/#kronav2meta state=Create
javax.persistence.PersistenceException: [PersistenceUnit: kronav2meta] Unable to build EntityManagerFactory
....
Caused by: org.hibernate.HibernateException: Missing column: appId in KRONAV2.A$_CONTEXTDATA
	at org.hibernate.mapping.Table.validateColumns(Table.java:277)
	at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1116)
	at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:139)
	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:349)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327)
	at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
	... 56 more
И как резюм в конце деплоя:

DEPLOYMENTS IN ERROR:
  Deployment "persistence.unit:unitName=kronav2ear.ear/#kronav2" is in error due to the following reason(s):
		org.hibernate.HibernateException: Missing column: appId in KRONAV2.A$_CONTEXTDATA
	at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:993)
	at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:939)
	at org.jboss.deployers.plugins.main.MainDeployerImpl.checkComplete(MainDeployerImpl.java:873)
	at org.jboss.system.server.profileservice.repository.MainDeployerAdapter.checkComplete(MainDeployerAdapter.java:128)
	at org.jboss.system.server.profileservice.hotdeploy.HDScanner.scan(HDScanner.java:369)
	at org.jboss.system.server.profileservice.hotdeploy.HDScanner.run(HDScanner.java:255)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
	at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
}


Ну и понятно, что если убрать составной ключ (т.е. сделать через @Id на скажем appId,
ну и в таблице поправить, то всё нормально работает)
...
Рейтинг: 0 / 0
03.04.2012, 12:42:42
    #37736152
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
AndreyDmt,
не делай составные.
Выгоды мало и тебе, и серверу.
...
Рейтинг: 0 / 0
03.04.2012, 12:52:40
    #37736196
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Возможно что @Column вообще игнорируется в Embeddable. Потому что ключ должен использоваться в разных таблицах.
У нас сделано через AttributeOverrides
http://stackoverflow.com/questions/331744/jpa-multiple-embedded-fields
http://stackoverflow.com/questions/3046677/automatically-add-a-prefix-to-column-names-for-embeddable-classes
http://stackoverflow.com/questions/951372/hibernate-mapping-a-second-embeddable-field-in-a-subclass
...
Рейтинг: 0 / 0
03.04.2012, 14:35:30
    #37736513
AndreyDmt
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Ну вообще я очень осторожно составные ключи пользую. Но вот понадобилось.
Меня напрягает, что в том же пакете практически идентичный комплект Первичный ключ-Ентити работал и работает
без проблем, я даже отличий не нахожу, кроме нюансов.
И аннотации там работают. А в дефектном не работают как в классе первичного ключа, так и в самом ентити.
Более того не работает не только @Column, но @Transient - то есть ничего :-))
...
Рейтинг: 0 / 0
03.04.2012, 14:41:13
    #37736531
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
AndreyDmtБолее того не работает не только @Column, но @Transient - то есть ничего :-))

Может из-за final ?
...
Рейтинг: 0 / 0
03.04.2012, 14:46:54
    #37736544
AndreyDmt
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
BlazkowiczAndreyDmtБолее того не работает не только @Column, но @Transient - то есть ничего :-))

Может из-за final ?

final сперва и не было. В туториал залез, там почему то с final пример. Поставил, ничего не поменялось
...
Рейтинг: 0 / 0
03.04.2012, 14:51:29
    #37736556
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Остаётся подебажить.
...
Рейтинг: 0 / 0
03.04.2012, 15:07:21
    #37736603
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
AndreyDmtНу вообще я очень осторожно составные ключи пользую. Но вот понадобилось.AndreyDmt,
я делал по началу составные ключи.... Что называется - экономил. Но потом, при добавлении связей и таблиц JOIN всё равно приходилось вводить суррогатные.
Напр. - каскад из Город-Район-Улица и т.д.
...
Рейтинг: 0 / 0
03.04.2012, 15:09:06
    #37736608
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Petro123я делал по началу составные ключи.... Что называется - экономил. Но потом, при добавлении связей и таблиц JOIN всё равно приходилось вводить суррогатные.
Напр. - каскад из Город-Район-Улица и т.д.
+1
...
Рейтинг: 0 / 0
03.04.2012, 15:19:32
    #37736640
AndreyDmt
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Составной ИД в ентити, ребус, крохсворд, загадка природы
Ну блин, оконфузился! Аж краска прошибает. Почувствуйте разницу:
Не работает
//
@EmbeddedId
private AaaContextDataKey contextDataKey;

public AaaContextDataKey getContextDataKey() {
return this.contextDataKey;
}

public void setContextDataKey(AaaContextDataKey contextDataKey) {
this.contextDataKey = contextDataKey;
}
Работает
//
private AaaContextDataKey contextDataKey;

@EmbeddedId
public AaaContextDataKey getContextDataKey() {
return this.contextDataKey;
}

public void setContextDataKey(AaaContextDataKey contextDataKey) {
this.contextDataKey = contextDataKey;
}
Тыща извинений за количество букв, при мизере проблем.
Точно понедельник виноват...
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Составной ИД в ентити, ребус, крохсворд, загадка природы / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]