Nesse caso, você usa a @JoinTableanotação JPA ?
Nesse caso, você usa a @JoinTableanotação JPA ?
Respostas:
EDIT 2017-04-29 : Como apontado por alguns dos comentaristas, o JoinTableexemplo não precisa do mappedByatributo de anotação. De fato, as versões recentes do Hibernate se recusam a iniciar, imprimindo o seguinte erro:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Vamos fingir que você tem uma entidade chamada Projecte outra entidade chamadaTask e cada projeto pode ter muitas tarefas.
Você pode projetar o esquema do banco de dados para este cenário de duas maneiras.
A primeira solução é criar uma tabela denominada Projecte outra tabela denominada Taske adicionar uma coluna de chave estrangeira à tabela de tarefas denominada project_id:
Project Task
------- ----
id id
name name
project_id
Dessa forma, será possível determinar o projeto para cada linha na tabela de tarefas. Se você usar essa abordagem, em suas classes de entidade, não precisará de uma tabela de junção:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
A outra solução é usar uma terceira tabela, por exemplo Project_Tasks, e armazenar o relacionamento entre projetos e tarefas nessa tabela:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
A Project_Taskstabela é chamada "Tabela de junção". Para implementar esta segunda solução no JPA, você precisa usar a @JoinTableanotação. Por exemplo, para implementar uma associação unidirecional um para muitos, podemos definir nossas entidades da seguinte forma:
Project entidade:
@Entity
public class Project {
@Id
@GeneratedValue
private Long pid;
private String name;
@JoinTable
@OneToMany
private List<Task> tasks;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
}
Task entidade:
@Entity
public class Task {
@Id
@GeneratedValue
private Long tid;
private String name;
public Long getTid() {
return tid;
}
public void setTid(Long tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Isso criará a seguinte estrutura de banco de dados:
A @JoinTableanotação também permite personalizar vários aspectos da tabela de junção. Por exemplo, se tivéssemos anotado a taskspropriedade assim:
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
O banco de dados resultante teria se tornado:
Por fim, se você deseja criar um esquema para uma associação muitos-para-muitos, o uso de uma tabela de junção é a única solução disponível.
@JoinTable/@JoinColumnpode ser anotado no mesmo campo com mappedBy. Assim, o exemplo correcta deve ser manter o mappedByna Project, e mover o @JoinColumnpara Task.project (ou vice-versa)
Project_Tasksprecisa do namede Taskbem, que se torna três colunas: project_id, task_id, task_name, como conseguir isso?
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
Também é mais limpo de usar @JoinTable quando uma Entidade pode ser a criança em vários relacionamentos pai / filho com diferentes tipos de pais. Para acompanhar o exemplo de Behrang, imagine que uma Tarefa possa ser filha de Projeto, Pessoa, Departamento, Estudo e Processo.
A tasktabela deve ter 5 nullablecampos de chave estrangeira? Eu acho que não...
É a única solução para mapear uma associação ManyToMany: você precisa de uma tabela de junção entre as duas tabelas de entidades para mapear a associação.
Também é usado para associações OneToMany (geralmente unidirecionais) quando você não deseja adicionar uma chave estrangeira na tabela do lado muitos e, assim, mantê-lo independente do lado.
Pesquise @JoinTable na documentação do hibernate para obter explicações e exemplos.
Ele permite que você lide com o relacionamento Muitos para Muitos. Exemplo:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
Ingressar na tabela permite criar um mapeamento usando:
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
irá criar uma tabela:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|
@ManyToMany associaçõesNa maioria das vezes, você precisará usar a @JoinTableanotação para especificar o mapeamento de um relacionamento de tabela muitos para muitos:
Portanto, supondo que você tenha as seguintes tabelas de banco de dados:
Na Postentidade, você mapeará esse relacionamento, assim:
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private List<Tag> tags = new ArrayList<>();
A @JoinTableanotação é usada para especificar o nome da tabela por meio do nameatributo, bem como a coluna Chave Externa que faz referência à posttabela (por exemplo, joinColumns) e a coluna Chave Estrangeira na post_tagtabela de links que faz referência à Tagentidade por meio do inverseJoinColumnsatributo.
Observe que o atributo em cascata da
@ManyToManyanotação está definido comoPERSISTeMERGEsomente porque a cascataREMOVEé uma má ideia, já que a instrução DELETE será emitida para o outro registro pai,tagno nosso caso, não para opost_tagregistro. Para mais detalhes sobre este tópico, consulte este artigo .
@OneToManyAssociaçõesAs @OneToManyassociações unidirecionais , que carecem de@JoinColumn mapeamento, se comportam como relacionamentos de tabela muitos para muitos, em vez de um para muitos.
Portanto, supondo que você tenha os seguintes mapeamentos de entidade:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
//Constructors, getters and setters removed for brevity
}
O Hibernate assumirá o seguinte esquema de banco de dados para o mapeamento de entidade acima:
Como já explicado, o @OneToManymapeamento JPA unidirecional se comporta como uma associação muitos-para-muitos.
Para personalizar a tabela de links, você também pode usar a @JoinTableanotação:
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JoinTable(
name = "post_comment_ref",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "post_comment_id")
)
private List<PostComment> comments = new ArrayList<>();
E agora, a tabela de links será chamada post_comment_refe as colunas Foreign Key serão post_id, para a posttabela e post_comment_idpara a post_commenttabela.
@OneToManyAssociações unidirecionais não são eficientes; portanto, é melhor usar@OneToManyassociações bidirecionais ou apenas o@ManyToOnelado. Confira este artigo para obter mais detalhes sobre este tópico.