Mapeamento one-to-one com pk-fk - socorro!

Amigos, me ajudem…

Fiz tudo direitinho, olha aí…

No meu banco de dados eu criei:

CREATE TABLE tablea( id integer NOT NULL DEFAULT nextval('tablea_seq'::regclass), CONSTRAINT tablea_pkey PRIMARY KEY (id) ) CREATE TABLE tableb( id integer NOT NULL, CONSTRAINT tableb_pkey PRIMARY KEY (id), CONSTRAINT tableb_fkey FOREIGN KEY (id) REFERENCES tablea (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION )

No meu código criei as duas tabelas (TableA e TableB):

[code]@Entity (name=“TableA”)
@SequenceGenerator(name = “tablea_seq”, sequenceName = “tablea_seq”)
@Table (schema=“public”, name=“tablea”)
public class TableA {

@Id
@GeneratedValue(
	strategy = GenerationType.AUTO, 
	generator = "tablea_seq"
)
@Column (name="id")
private Integer id;

@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)  
@PrimaryKeyJoinColumn
private TableB tableB;


public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public TableB getTableB() {
	return tableB;
}
public void setTableB(TableB tableB) {
	this.tableB = tableB;
}

}[/code]

[code]@Entity (name=“TableB”)
@Table (schema=“public”, name=“tableb”)
public class TableB {

@GenericGenerator(name = "gerador", strategy = "foreign", 
	parameters = @Parameter(name = "property", value = "tableA"))
@Id
@GeneratedValue(generator = "gerador")   
@Column(name = "id")
private Integer id;

@OneToOne(mappedBy = "tableB", fetch = FetchType.LAZY)
private TableA tableA;


public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public TableA getTableA() {
	return tableA;
}
public void setTableA(TableA tableA) {
	this.tableA = tableA;
}

}[/code]

…e o teste:

TableA tableA = new TableA(); TableB tableB = new TableB(); tableA.setTableB(tableB); tableB.setTableA(tableA); dao.incluir(tableA);

…e tudo o que tenho é a exceção abaixo:

01:12:47,890 ERROR JDBCExceptionReporter:234 - ERROR: insert or update on table "tableb" violates foreign key constraint "tableb_fkey" Detail: Key (id)=(5) is not present in table "tablea".

Então, está gerando a sequencia (como vê acima = 5), mas parece estar violando a foreignkey da TableB. Detalhe: as duas tabelas estão em branco (sem registros). A cada nova tentativa é gerado uma sequencia, mas sem sucesso na inclusão dos registros. Dá a entender que primeiro tem de gravar na tableA, para depois gravar na tableB, mas não está ocorrendo…

Me ajudem aí, estou no sufoco com isto, precisando resolver. Passei o dia pesquisando isto e a única solução que existe é esta, mas não está funcionando…

Obrigado a todos.

você ja tento no lugar do @PrimaryKey usa @JoinColumn(name=“tabelaA”) ?

Violação do chava por conta disso aki:

@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL) @PrimaryKeyJoinColumn private TableB tableB;

Eu faço assim:


public class Pessoa{

  private Long idPessoa;
  private Sogra sogra;

  @Id
  @Column(name="IDPESSOA");
  public Long getIdPessoa(){
        return idPessoa;
  }

   
  @OneToOne(cascade = CascadeType.ALL)
  @JoinColumn(name="IDSOGRA" )
  @ForeignKey (name="FK_PESSOA_SOGRA")  
  public Sogra getSogra(){
      return sogra;
  }

}

Isso deve resolver. Posso estar esquecendo algum atributo, mas daí você dá uma lida na documentação do hibernate annotatios

Sim, tentei assim em TableA:

@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL) @JoinColumn(name="tableA") private TableB tableB;
…e o resultado é o mesmo:

13:41:38,617 ERROR JDBCExceptionReporter:234 - ERROR: insert or update on table "tableb" violates foreign key constraint "tableb_fkey" Detail: Key (id)=(9) is not present in table "tablea".

[quote]Violação do chava por conta disso aki:
@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private TableB tableB;[/quote]
Retirei isto “@PrimaryKeyJoinColumn” e o resultado foi:

13:46:25,904 ERROR JDBCExceptionReporter:234 - ERROR: insert or update on table "tableb" violates foreign key constraint "tableb_fkey" Detail: Key (id)=(10) is not present in table "tablea".

Quanto a observação do odd.silva, só é válida quando as tabelas possuem o relacionamento assim:

<pk> ------<fk><uk>

Neste caso funciona perfeitamente, no entanto estou tentando do jeito correto (pk —> pk-fk), e não estou obtendo sucesso.

Segundo a documentação, o correto é fazer exatamente do jeito que eu fiz. Será que é algum bug?
Detalhe:
Quando eu recupero a tableA que já existe no banco, aí a tableB é inserida e não ocorre exception. No entanto, se eu tentar inserir somente a tableA, mesmo colocando optional=true no relacionamento de ambos, ocorre esta exception:

13:53:22,014 ERROR HibernateConvertException:37 - THROWABLE -->javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.eti.amazu.appblank.domain.TableA.tableB

Ou seja: para persisir TableA a TableB não pode ser nula.

Alguém aí tem novas idéias?
Alguém já tentou onoToOne com pk —> pk-fk?

Me parece um bug em JPA…

Obrigado, e continuo aguardando novas idéias de alguém que já tenha feito isto.

apaga seu banco e pedi pro jpa cria as tabelas pra vc, eu fiz do jeito que falei acima pra você e funciono, nunca tive problemas.

OK, tentei ao invés de “@JoinColumn(name=“tableA”)”, coloquei @JoinColumn(name=“id”).
Resultado:
Parabéns tiago e Mr.style, ambos estão corretos!
parabéns também ao oddy.silva. A sua colocação para a TableA também está correta. (lembrando que o join não é com o objeto “tableA” mas sim com o “id” da coluna tableA).
FUNCIONOU - - PROBLEMA RESOLVIDO.

Abaixo vai o código completo e corrigido:

[code]@Entity (name=“TableA”)
@SequenceGenerator(name = “tablea_seq”, sequenceName = “tablea_seq”)
@Table (schema=“public”, name=“tablea”)
public class TableA {

@Id
@GeneratedValue(
	strategy = GenerationType.AUTO, 
	generator = "tablea_seq"
)
@Column (name="id")
private Integer id;

@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)  
@JoinColumn(name="id")
private TableB tableB;


public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public TableB getTableB() {
	return tableB;
}
public void setTableB(TableB tableB) {
	this.tableB = tableB;
}

}[/code]

[code]@Entity (name=“TableB”)
@Table (schema=“public”, name=“tableb”)
public class TableB {

@GenericGenerator(name = "gerador", strategy = "foreign", 
	parameters = @Parameter(name = "property", value = "tableA"))
@Id
@GeneratedValue(generator = "gerador")   
@Column(name = "id")
private Integer id;

@OneToOne(mappedBy = "tableB", fetch = FetchType.LAZY)
private TableA tableA;


public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public TableA getTableA() {
	return tableA;
}
public void setTableA(TableA tableA) {
	this.tableA = tableA;
}

}
[/code]

É nóis. :smiley:

Pessoal, desculpe ressuscitar o tópico, mas me deparei com um problema estranho.
o relacionamento funciona somente quando tento inserir tableA e tableB concomitantemente.
Caso eu jah tenha o registro em tableA e tento persistir a tableB, simplesmente não ocorre nada (o cosole printa a sql insert em tableB - tem-se a impressão de haver o insert em tableB), mas quando vou olhar a tabela, o registro não eh inserido… estranho.

TableA tableA = dao.recuperar(nrRegistro); //recupera a tableA, deixando-a gerenciada. TableB tableB = new TableB(); tableB.setTableA(tableA); tableA.setTableB(tableB); dao.persist(tableB);
E aí, onde estou errando? (lembrando que o mapeamento eh ---->
Desde já agradeço a todos.

Simplesmente retirei do spring a configuração abaixo e tudo voltou a funcionar direito:

<prop key="hibernate.connection.release_mode">auto</prop>

Mas afinal, então naum entendi direito para que isto serve!!!
Obrigado a todos.