JPA e SecondaryTable

3 respostas
D

Olá pessoal,

Há alguns dias tenho problema com JPA, sem obter nenhum sucesso. Tenho duas tabelas em um banco de dados legado e preciso mapeá-las para uma única classe Java, mas estou obtendo um erro. As tabelas são as seguintes:

create table tb_servidor (
  cd_servidor number primary key,
  cd_tipo number,
  ...
  cd_nome number,
  FOREIGN KEY(cd_nome) REFERENCES tb_nome(cd_nome) 
) 

create table tb_nome(
  cd_nome number primary key,
  nm_nome varchar2(32000)
)

A classe Java que implementei é a seguinte:

package entity;
import ...
@Entity
@Table(name = "TB_SERVIDOR")
@SecondaryTable(name = "TB_NOME", 
		pkJoinColumns = { @PrimaryKeyJoinColumn(name = "CD_NOME", referencedColumnName = "CD_NOME") })
public class Juiz{

	@Column(name = "cd_servidor", nullable = false)
	@Id
	private int codigo;
//Se eu tirar esse campo e a anotação SecondaryTable, tudo funciona, mas não faz o que eu quero.
//Ademais já tentei usar um ManyToOne ou OneToOne aqui, mas também não funcionou.
	@Column(table="TB_NOME", name = "NM_NOME")
	private String nome;

	public int getCodigo() {
		return codigo;
	}

	public void setCodigo(int codigo) {
		this.codigo = codigo;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + codigo;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Juiz other = (Juiz) obj;
		if (codigo != other.codigo)
			return false;
		return true;
	}

}

O código JUnit que testa a classe acima é

package entity;
import ...
public class JuizTest {

	private EntityManagerFactory emf;
	private EntityManager em;

	@Before
	public void initEmfAndEm() {
		Logger.getLogger("org").setLevel(Level.ERROR);

		emf = Persistence
				.createEntityManagerFactory("jurisprudenciaPersistenceUnit");
		em = emf.createEntityManager();

	}

	@After
	public void cleanup() {
		if (em != null)
			em.close();
	}

	@SuppressWarnings("unchecked")
	@Test
	public void insertAndRetrieve() {
		em.getTransaction().begin();

		List<Juiz> list = em.createQuery(
				"select DISTINCT p from Juiz p where p.codigo=74")
				.getResultList();
		assertEquals(1, list.size());
		for (Juiz c : list) {
			System.out.println(c);
		}

	}

}

O erro encontrado é o seguinte

javax.persistence.PersistenceException: org.hibernate.MappingException: Unable to find column with logical name: CD_NOME in org.hibernate.mapping.Table(TB_SERVIDOR) and its related supertables and secondary tables
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:258)
	at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:120)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:37)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:27)
	at entity.JuizTest.initEmfAndEm(JuizTest.java:28)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:122)
	at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:86)
	at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
	at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
	at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
	at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.MappingException: Unable to find column with logical name: CD_NOME in org.hibernate.mapping.Table(TB_SERVIDOR) and its related supertables and secondary tables
	at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:394)
	at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:231)
	at org.hibernate.cfg.annotations.EntityBinder.bindJoinToPersistentClass(EntityBinder.java:519)
	at org.hibernate.cfg.annotations.EntityBinder.createPrimaryColumnsToSecondaryTable(EntityBinder.java:509)
	at org.hibernate.cfg.annotations.EntityBinder.finalSecondaryTableBinding(EntityBinder.java:440)
	at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:770)
	at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:498)
	at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:277)
	at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115)
	at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1269)
	at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:150)
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:888)
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:186)
	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:246)
	... 24 more

3 Respostas

D

Eu estou achando que o problema é porque cd_nome não é chave primária na tabela tb_servidor, mas apenas foreign key, e que, para @SecondaryTable, a coluna referenciada precisa fazer parte da chave primária em ambas as tabelas. Se o problema for esse não sei nem que annotation usar para resolver a questão ou, ainda, se JPA possui solução para tal problema.

D

Continua em http://www.guj.com.br/posts/list/70682.java

C

up

Criado 2 de outubro de 2007
Ultima resposta 20 de mar. de 2008
Respostas 3
Participantes 2