Hibernate- Dúvida no mapeamento many-to-one com composite-id

4 respostas
cnino

Oi, pessoas! :-o

Estou com um pouco de dificuldades em mapear corretamente uma relação entre duas tabelas.

Bom, estou trabalhando com a tabela SECAO e a tabela REGRA:

Tenho a seguinte relação entre elas:
SECAO many-to-one REGRA

O problema que eu tenho é na tabela SECAO tenho como PK a coluna SECAO_ID, mas para REGRA, tenho uma chave composta das colunas REGRA_ID e FORMULARIO_ID.

Minha dúvida é como fazer esse mapeamento da Regra dentro da Secao… :?

Bom, o mapeamento Hibernate da tabela REGRA foi feito da seguinte maneira:

<class name="domain.Regra" table="REGRA"> 
    <composite-id class="domain.RegraId" name="regraId" mapped="false">
        <key-property column="REGRA_ID" name="regraId" type="java.lang.Long"/>
        <key-many-to-one column="FORMULARIO_ID" name="formulario" class="domain.Formulario"/>
    </composite-id>
    <property column="TITULO" name="titulo" type="java.lang.String"/>
  </class>

Agora, no mapeamento da SECAO, como eu posso colocar a referência para a REGRA, sendo que devo referenciar duas colunas? :cry:

<class name="domain.Secao" table="SECAO"> 
    <id column="SECAO_ID" name="id" type="java.lang.Long" /> 
	
    <mapeamento para REGRA>

  </class>

Não basta eu fazer algo do tipo:

<property column="REGRA_ID" name="regra" type="domain.Regra"/>

porque na real, devem ser duas colunas que correspondem a um objeto… :roll:

E eu ainda teria que colocar um mapeamento para REGRA sobre a SECAO, não?

Não sei se me fiz entender no problema… mas alguém já trabalhou com isso?

Valeu!

4 Respostas

cnino

Bom, tentei mapear a REGRA na SECAO da seguinte forma:

<class name="domain.Secao" table="SECAO">   
  <id column="SECAO_ID" name="id" type="java.lang.Long" />   
  <many-to-one name="regra" class="domain.Regra">
     <column name="REGRA_ID"/>
     <column name="FORMULARIO_ID"/>
  </many-to-one>
</class>

E ainda, no mapeamento da REGRA, coloquei um set de SECAO:

<class name="domain.Regra" table="REGRA">   
  <composite-id class="domain.RegraId" name="regraId" mapped="false">  
      <key-property column="REGRA_ID" name="regraId" type="java.lang.Long"/>  
      <key-many-to-one column="FORMULARIO_ID" name="formulario" class="domain.Formulario"/>  
  </composite-id>  
  <property column="TITULO" name="titulo" type="java.lang.String"/> 
  <set name="secoes" cascade="all-delete-orphan" inverse="true">
    	<key>
    		<column name="REGRA_ID"/>
    		<column name="FORMULARIO_ID"/>    		
    	</key>
    	<one-to-many class="domain.Secao"/>
    </set>
</class>

Dessa forma, não obtenho nenhum erro no mapeamento…
Mas, o estranho é que quando pego um objeto Secao, o atributo regra vem sempre nulo… :? (mesmo que tenha valores no banco…)
Ah, sim… claro… não esqueci de colocar um atributo regra do tipo domain.Regra na minha classe domain.Secao…
Assim como tenho um Set<domain.Secao> na classe domain.Regra.

Alguém já passou por isso?

cnino

Ei!

Este último mapeamento que eu postei aqui está correto! :smiley:

Ele funcionou… e na verdade eu estava era com um problema de inconsistência de dados que estavam na tabela. :oops:

Bom, mas fica aí a dica para a posteridade, pra quem se deparar com o mesmo problema! :lol:

Valeu!

P

Estou tendo o mesmo problema, porém utilizando jpa e hibernate.

Classe TipoExtintor

public class TipoExtintor {


	@Sort(type = SortType.UNSORTED, comparator = TipoExtintorCapacidade.class)
	@OneToMany(fetch=FetchType.EAGER)
	@JoinColumn(name="num_tipo_extint_ctex")
	@Cascade({CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DELETE_ORPHAN})
	private Set<TipoExtintorCapacidade> listaTipoExtintorCapacidade = new HashSet<TipoExtintorCapacidade>();
}

Classe TipoExtintorCapacidade

public class TipoExtintorCapacidade {
	@Id
	@Column(name = "num_tipo_extint_ctex")
	private Integer idTipoExtintor;

	@Id
	@Column(name = "num_val_capac_ctex")
	private Integer idCapacidade;

	@ManyToOne
	@JoinColumn(name = "num_tipo_extint_ctex", insertable = false, updatable = false)
	private TipoExtintor tipoExtintor;

	@ManyToOne
	@JoinColumn(name = "num_val_capac_ctex", insertable = false, updatable = false)
	private Capacidade capacidade;

	
	@Column(name = "valorRecarga", nullable = false)
	private double valorRecarga;
}

O TipoExtintor possui um set contendo dois objetos TipoExtintorCapacidade.
Eu retiro um objeto TipoExtintorCapacidade tento efetuar um merge(TipoExtintor);

O log do servidor retorna

11:22:59,394 DEBUG [SQL]

lista os objetos

select

tipoextint0_.num_seq_tei as num1_9_1_,

tipoextint0_.sigla_tei as sigla2_9_1_,

tipoextint0_.desc_tei as desc3_9_1_,

tipoextint0_.tipo_carga_tei as tipo4_9_1_,

tipoextint0_.possui_num_pat as possui5_9_1_,

tipoextint0_.indic_sit_tei as indic6_9_1_,

tipoextint0_.prazo_insp_tei as prazo7_9_1_,

tipoextint0_.prazo_nova_carga_tei as prazo8_9_1_,

tipoextint0_. prazo_teste_hidrost_tei as column9_9_1_,

listatipoe1_.num_tipo_extint_ctex as num1_3_,

listatipoe1_.num_val_capac_ctex as num2_3_,

listatipoe1_.num_tipo_extint_ctex as num1_10_0_,

listatipoe1_.num_val_capac_ctex as num2_10_0_,

listatipoe1_.valorRecarga as valorRec3_10_0_,

listatipoe1_.valorTesteHidrostatico as valorTes4_10_0_

from

ext.tipo_extintor_incendio tipoextint0_

left outer join

ext.capacidade_tipo_extintor listatipoe1_

on tipoextint0_.num_seq_tei=listatipoe1_.num_tipo_extint_ctex

where

tipoextint0_.num_seq_tei=?

11:22:59,441 DEBUG [SQL]

select

capacidade0_.num_seq_vcex as num1_0_0_,

capacidade0_.val_vcex as val2_0_0_,

capacidade0_.indic_sit_vcex as indic3_0_0_

from

ext.valor_possivel_capac_extint capacidade0_

where

capacidade0_.num_seq_vcex=?

11:22:59,441 DEBUG [SQL]

select

capacidade0_.num_seq_vcex as num1_0_0_,

capacidade0_.val_vcex as val2_0_0_,

capacidade0_.indic_sit_vcex as indic3_0_0_

from

ext.valor_possivel_capac_extint capacidade0_

where

capacidade0_.num_seq_vcex=?

exibe conteúdo

11:22:59,488 DEBUG [Printer] listing entities:

11:22:59,488 DEBUG [Printer] com.aplicacao.Capacidade{situacao=1, capacidade=2, idCapacidade=1}

11:22:59,488 DEBUG [Printer] com.aplicacaonegocio.TipoExtintorCapacidade{tipoExtintor=com.aplicacaonegocio.TipoExtintor#2, valorRecarga=0.0, valorTesteHidrostatico=0.0, capacidade=com.aplicacaonegocio.Capacidade#3}

11:22:59,488 DEBUG [Printer] com.aplicacaonegocio.Capacidade{situacao=2, capacidade=3, idCapacidade=3}

11:22:59,488 DEBUG [Printer] com.aplicacaonegocio.TipoExtintor{prazoInspecao=0, codigo=e, tipoCarga=1, prazoTesteHidrostatico=0, possuiNumeroPat=1, situacao=2, listaTipoExtintorCapacidade=[com.aplicacao…negocio.TipoExtintorCapacidade], descricao=a, idTipoExtintor=2, prazoRecarga=0}

11:22:59,488 DEBUG [Printer] com.aplicacaonegocio.TipoExtintorCapacidade{tipoExtintor=com.aplicacaonegocio.TipoExtintor#2, valorRecarga=0.0, valorTesteHidrostatico=0.0, capacidade=com.aplicacaonegocio.Capacidade#1}

Ao invés de efetuar o delete, ele efetua um update

11:22:59,488 DEBUG [SQL]

update

ext.capacidade_tipo_extintor

set

num_tipo_extint_ctex=null

where

num_tipo_extint_ctex=?

and num_tipo_extint_ctex=?

and num_val_capac_ctex=?

11:22:59,628 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: null

11:22:59,628 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: null

11:22:59,628 ERROR [JDBCExceptionReporter] Entrada em lote 0 update ext.capacidade_tipo_extintor set num_tipo_extint_ctex=null where num_tipo_extint_ctex=2 and num_tipo_extint_ctex=2 and num_val_capac_ctex=3 foi abortada. Chame getNextException para ver a causa.

11:22:59,628 ERROR [JDBCExceptionReporter] Entrada em lote 0 update ext.capacidade_tipo_extintor set num_tipo_extint_ctex=null where num_tipo_extint_ctex=2 and num_tipo_extint_ctex=2 and num_val_capac_ctex=3 foi abortada. Chame getNextException para ver a causa.

11:22:59,628 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: 23502

Exibe erro sqlState 23502 - Um valor de inserção ou de atualização é nulo, mas a coluna não pode conter valores nulos.

11:22:59,628 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: 23502

11:22:59,628 ERROR [JDBCExceptionReporter] ERROR: null value in column num_tipo_extint_ctex violates not-null constraint

11:22:59,628 ERROR [JDBCExceptionReporter] ERROR: null value in column num_tipo_extint_ctex violates not-null constraint

11:22:59,644 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session

aqui vem a exceção

org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

Pergunta???
Por que ele efetua update e não delete?

P

Resolvido o problema.
Segui as instruções do artigo:
http://marloncarvalho.net/wordpress/?p=34

O mapeamento das classes ficou:

public class TipoExtintorCapacidade implements Serializable, Comparable {

	private static final long serialVersionUID = -1746284116192915690L;

	@EmbeddedId
	private TipoExtintorCapacidadePK id;
}


@Embeddable
public class TipoExtintorCapacidadePK implements Serializable {

	@Column(name = "num_tipo_extint_ctex")
	private Integer idTipoExtintor;

	@Column(name = "num_val_capac_ctex")
	private Integer idCapacidade;
}


public class TipoExtintor implements Serializable{
	
	@Sort(type = SortType.UNSORTED, comparator = TipoExtintorCapacidade.class)
	@OneToMany(fetch=FetchType.EAGER, mappedBy="id.idTipoExtintor")
	@Cascade({CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DELETE_ORPHAN})
	private Set<TipoExtintorCapacidade> listaTipoExtintorCapacidade = new HashSet<TipoExtintorCapacidade>();
}
Criado 25 de fevereiro de 2009
Ultima resposta 27 de fev. de 2009
Respostas 4
Participantes 2