[RESOLVIDO] Modelagem Relacional Não atendida pelo OneToMany da JPA2

Fala ae rapaziada, tudo tranquilo?

É o seguinte, estou com uma dúvida/dificuldade em implementar um MER com JPA2. Quem puder me ajudar, pois já procurei bastante e não achei nenhuma dúvida/dificuldade igual a minha, eu agradeço e acho que poderá ser dúvida de outros também.

Tenho as Entidades chamadas Aposta e Jogada.
1º caso: O Jogador pode fazer várias apostas, mas a Aposta pertence a só um Apostador, ou seja, [Apostador]1->N[Apostas].
2º caso: Várias Apostas podem ser realizadas em uma Jogada, e apenas para aquela Jogada, consequentemente a Jogada possui N apostas, ou seja, um [Apostas]N->1[Jogada].

O problema ocorre no momento em que são criadas as tabelas do BD com a JPA.

No primeiro caso o mapeamento para a JPA foi numa boa, de acordo com minha MER, pois a Aposta pertence/possui um Apostador, então a tabela Aposta é criada com o ID de Apostador(apostador_id).

@Entity
@PrimaryKeyJoinColumn(name="pessoa_id")
public class Apostador extends Pessoa {

	@Column(name="data_nascimento", nullable=false)
	private Calendar dataNascimento;
	
	@Column(length=1, nullable=false)
	private char sexo;

	// get e set
}

@Entity
public class Aposta {
	@Id  @GeneratedValue
	private Long id;

	@ManyToOne  @JoinColumn(name="apostador_id", nullable=false)
	private Apostador apostador;

	// get e set
}

No segundo caso a JPA não cria as tabelas conforme minha Modelagem Relacional, onde a tabela Jogada possua o ID das Apostas (aposta_id), ela cria uma Nova Tabela chamada jogada_aposta contendo o ID da Jogada e o ID da Aposta. :frowning:

@Entity
public class Jogada {

	@Id  @GeneratedValue
	private Long id;

	@OneToMany  @Column(name="aposta_id")
	private List<Aposta> listaAposta;

	// get e set
}

Como eu poderia mapear minhas classes Aposta e Jogada afim de que o ID da Aposta seja registrado diretamente na tabela Jogada?
Espero ter conseguido passar minha dúvida/dificuldade. :slight_smile:

Abraço e Sucesso…

Provavelmente você não leu a parte da documentação do hibernate que diz que “mesmo em relacionamentos 1 : N é mais interessante utilizar uma tabela associativa para gerenciar este relacionamento” (ok, o texto não é esse, mas o sentido é o mesmo).
Ou seja, se você mapear algo somente com @OneToMany, o hibernate criará 3 tabelas: A tabela table1, a tabela table2 e a tabela associativa table1_table2…
Ok, drsmachado, mas e o @Column que eu coloquei ali?
Este cara não tem influência nesta relação, logo, com ou sem ele, o problema persiste.
Para resolver isso, substitua o @Column pelo @JoinColumn

@Entity  
public class Jogada {  
  
    @Id  @GeneratedValue  
    private Long id;  
  
    @OneToMany
    @JoinColumn(name = "aposta_id")
    private List<Aposta> listaAposta;  
  
    // get e set  
}  

Fala ae drsmachado, tudo bom?

Rapaz, você falou sobre a documentação do Hibernate, mas isso não seria documentação da JPA?

E realmente não estou utilizando a documentação do Hibernate, e nem mesmo da JPA, pois como meu inglês não é dos melhores eu estava com uma curva de aprendizado não muito boa.
Meu material de referência no momento está sendo o Mini Livro de JPA2 do Hebert, http://uaihebert.com/jpa-mini-livro-primeiros-passos-e-conceitos-detalhados/ , que estou achando muito bom aliás.

Enfim, percebi esse comportamento da JPA, mas resolvi perguntar aqui porque acho desnecessário a criação desta nova tabela associativa no BD. Me parece criar um aumento no custo das consultas ao Banco e aumentar a complexidade de Queries.
Quanto a utilizar o @JoinColumn, eu fiz isso, mas no momento de criar as tabelas estava dando erro, então coloquei o @Column mesmo para tirar essa dúvida aqui.

Mas se não tem solução, solucionado está. :slight_smile:

Agradeço a atenção.

Abraço e Sucesso…

A necessidade da criação da terceira tabela(tabela de relacionamento ou join table) é da especificação do JPA e ocorre nos relacionamentos One To Many. Já o inverso, nos relacionamentos Many To One a criação da join table não ocorre.

Apenas para constar para futuras pesquisas.

De fato. Como eu não sabia qual era a implementação que usava, logo presumi que fosse hibernate. Desta forma, o comportamento natural é este.
Como disse, é possível “resolver” isso, colocando a anotação @JoinColumn.

Fala ae Agent K e drsmachado.

Então, colocar o @JoinColumn para o relacionamento @OneToMany não rolou. Estava dando erro.
E a JPA cria a nova tabela com o nome do campo sendo o mesmo do atributo no Java. A propriedade name do @JoinColumn neste caso não funcionaria, pois é um atributo do tipo List.

@OneToMany
private List<Aposta> listaAposta;

Resumindo, tive de deixar a classe Jogada sem o @JoinColumn(name=“aposta_id”) e criar eu mesmo a classe Associativa que gerará uma Tabela Associativa no BD, e assim nela criar o atributo com o nome correto através do @ManyToOne @JoinColumn(name="").

Mas uma dúvida fiquei.
Neste projeto sendo inicializado do Zero, com o Modelo de Dados sendo criado a partir do modelo de Classe com a JPA o problema é até pequeno, porém e se o Modelo de Dados já existir e estiver sendo utilizado, como seria implementar essa dificuldade de Mapeamento do JPA sobre ele?.. 8-\

Abraço…