[RESOLVIDO] Chave primária composta com String

Boa dia a todos,

estou com um problema sério: tenho um banco legado para mapear, e estou agora trabalhando com duas tabelas que tem os campos conforme a figura: (os nomes reais das tabelas nao sao esses, mas fiz assim pra ficar mais facil de entender)

Eu criei a @Embeddable para Documento com as três chaves e funcionou.
Depois mapeei Observacao com um @Embeddable com as quatro chaves primárias também.
Referenciei uma lista de observações no Documento e um documento para Observacao. Porém, está dando erro de conversão. Eu pesquisei e uma causa seria o fato de usar Strings como chaves primárias.

O banco é legado, estas duas tabelas nao tem chave primária decente, são essas aí mesmo… Então o que posso fazer para conseguir mapear estas tabelas? Ou tenho que fazer uma sql mesmo pra fazer o Documento carregar as Observacoes e vice-versa?

1 min que vou postar os códigos e o erro…

Na verdade a chave primária é o embeddable do documento mais o int obs_numero e não os três novamente.

Ok caríssimos, estou postando o que fiz ate agora e o erro que me voltou:

/* Classe Documento */
@Entity
@Table(name = "tb_documento")
public class Documento {

	@EmbeddedId
	private DocumentoPk documentoPk;
	
	@OneToMany(mappedBy = "documento", fetch = FetchType.LAZY)
	private List<Observacao> listObservacao;
	
	(...)
/* Classe DocumentoPk */
@Embeddable
public class DocumentoPk implements Serializable {

	@Column(name = "doc_codigo")
	private String codigo;

	@Column(name = "doc_versao")
	private Integer versao;

	@Column(name = "doc_tp_documento")
	private String tipoDocumento;
	
	(...)
/* Classe Observacao */
@Entity
@Table(name = "tb_observacao")
public class Observacao {

	@EmbeddedId
	private ObservacaoPk observacaoPk;
	
	@ManyToOne
    @JoinColumns({ 
		@JoinColumn(name = "doc_codigo", updatable = false, insertable = false), 
		@JoinColumn(name = "doc_versao", updatable = false, insertable = false),
		@JoinColumn(name = "doc_tp_documento", updatable = false, insertable = false) 
	})
	private Documento documento;
	
	(...)
/* Classe ObservacaoPk */
@Embeddable
public class ObservacaoPk implements Serializable {

	@Column(name = "obs_num")
	private Integer numero;

	@Column(name = "doc_codigo")
	protected String codigo;

	@Column(name = "doc_versao")
	private Integer versao;
	
	Column(name = "doc_tp_documento")
	private String tipoDocumento;
	
	(...)

O erro*:


org.hibernate.exception.GenericJDBCException: could not initialize a collection: [br.com.azi.model.Alim2.listInfracao#component[codigo,tipoDocumento,versao]{codigo=2831386290019960701OS17082010101040, tipoDocumento=AI, versao=1}]
	at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
	at org.hibernate.loader.Loader.loadCollection(Loader.java:2069)
	at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
	at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:628)
	at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
	at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1853)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
	at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506)
	at java.lang.String.valueOf(String.java:2826)
	at java.lang.StringBuilder.append(StringBuilder.java:115)
	at br.com.azi.teste.TesteHibernate.imprimeAlim(TesteHibernate.java:67)
	at br.com.azi.teste.TesteHibernate.execute(TesteHibernate.java:43)
	at br.com.azi.teste.TesteHibernate.main(TesteHibernate.java:25)
Caused by: java.sql.SQLException: Character to numeric conversion error
	at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:379)
	at com.informix.jdbc.IfxSqli.addException(IfxSqli.java:3109)----- FIM -----

	at com.informix.jdbc.IfxSqli.receiveError(IfxSqli.java:3419)
	at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2282)
	at com.informix.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2202)
	at com.informix.jdbc.IfxSqli.sendStatementQuery(IfxSqli.java:1450)
	at com.informix.jdbc.IfxSqli.executeStatementQuery(IfxSqli.java:1403)
	at com.informix.jdbc.IfxSqli.executeStatementQuery(IfxSqli.java:1333)
	at com.informix.jdbc.IfxResultSet.executeQuery(IfxResultSet.java:223)
	at com.informix.jdbc.IfxStatement.executeQueryImpl(IfxStatement.java:843)
	at com.informix.jdbc.IfxPreparedStatement.executeQuery(IfxPreparedStatement.java:244)
	at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
	at org.hibernate.loader.Loader.getResultSet(Loader.java:1849)
	at org.hibernate.loader.Loader.doQuery(Loader.java:718)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
	at org.hibernate.loader.Loader.loadCollection(Loader.java:2062)
	... 12 more

*Os nomes verdadeiros de Documento é Alim e de Observação é Infracao

Obrigada…

@Embeddable
public class ObservacaoPk implements Serializable {
    
  @Column(name = "obs_num")
  private Integer numero;
  
  @EmbeddId
  private DocumentoPk documento;

Vc diz que eu devo colocar um objeto DocumentoPk dentro do meu ObservacaoPk?

Vou tentar aqui e te falo :wink:

Agora o erro retornado foi este:

org.hibernate.AnnotationException: br.com.azi.model.InfracaoPk must not have @Id properties when used as an @EmbeddedId: br.com.azi.model.Infracao2.infracaoPk
	at org.hibernate.cfg.AnnotationBinder.bindComponent(AnnotationBinder.java:2201)
	at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1939)
	at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:762)
	at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:726)
	at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:636)
	at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:359)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1377)
	at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
	at br.com.azi.teste.TesteHibernate.<init>(TesteHibernate.java:19)
	at br.com.azi.teste.TesteHibernate.main(TesteHibernate.java:25)

Só uma observação: o campo número de Observação não pode ser usado como @Id, ele é um campo que serve para ordenar as observações de um documento (1a, 2a, 3a …)

O pior é que NENHUMA das tabelas desse banco tem PKs decentes :frowning: Por isso que eu to precisando desse encaminhamento
Eu to tentando outras formas aqui tb, quando encontrar a resposta eu posto aqui…

Abração

O número da observação é ou não é chave primária no banco ?
No embedded não pode ter a anotação Id … tem q ser na entidade.

É que teve um rapaz que me perguntou porque que eu não usava só o campo número como Id de Observação…
Aí expliquei pra que esse campo serve, e escrevi aqui pra nao ter de novo essa dúvida. A chave de Observação é a combinação do Documento ao qual ele se refere mais o número da observação dentro do documento, que nem tá lá em cima :slight_smile:

Então, em nenhuma das etidades tem @Id, está igual eu postei mesmo, só mudei que coloquei que nem vc falou:

@Embeddable
public class ObservacaoPk implements Serializable {

	/**
	 * Número da Infração
	 */
	@Column(name = "obs_num")
	private Integer numero;

	@EmbeddedId
	private DocumentoPk documento;

o resto foi mantido
Obrigada pela atenção!

Não sei se vc leu o erro q deu. Mas está me parecendo q a classe InfracaoPk tem a anotação Id. E isto não pode, porque ela é uma classe embedded. Foi este o erro q vc postou.

Pior que ela não tem… Nenhumas delas tem… Mas eu vou chutar aqui uma causa:

[code]@Entity
@Table(name = “notes_alim_inf”)
public class Infracao {

@EmbeddedId
private InfracaoPk infracaoPk;

[/code]

@Embeddable
public class InfracaoPk implements Serializable {

	/**
	 * Número da Infração
	 */
	@Column(name = "alim_inf_num")
	private Integer numeroInfracao;

	@EmbeddedId
	private AlimPk alim;

tá usando @EmbeddedId duas vezes, pode isso?
obrigada…

Huummm … e agora hein ? será isso ?
Vou pesquisar aqui.

CONSEGUIMOS!!! :smiley:

Vou só resolver um negócio e já posto aqui!
Mas vc teve participação importante, aluisiodsv!!
30 min que eu já posto os códigos ^^

TO SALVAAAAAA rsrsrsrs |o||o||o||o||o||o||o||o|

Classe Documento:

@Entity
@Table(name = "db_documento")
public class Documento {

	@EmbeddedId
	private DocumentoPk documentoPk;

	@OneToMany(mappedBy = "observacaoPk.documento", fetch = FetchType.LAZY)
	private List<Observacao> listObservacao;
(...)

A classe DocumentoPk permanece a mesma.

Classe Observacao:

@Entity
@Table(name = "tb_observacao")
public class Observacao {

	@EmbeddedId
	private ObservacaoPk observacao Pk;
(...)

Classe ObservacaoPk:

@Embeddable
public class ObservacaoPk implements Serializable {

	/**
	 * Número da Infração
	 */
	@Column(name = "doc_num")
	private Integer numero;

	@Embedded  // E não @EmbeddedId
	private DocumentoPk documento;
(...)

Isso por enquanto resolveu meu problema, agora consigo fazer:
documento.getListObservacoes()

Tomara que consiga salvar também, mas aqui já é um grande passo…

Obrigada aluisiodsv pela força!

Fico feliz em ajudar!!