Eu sou novo em hibernar e preciso usar relações um para muitos e muitos para um. É um relacionamento bidirecional em meus objetos, para que eu possa atravessar de qualquer direção. mappedBy
é a maneira recomendada de fazer isso, no entanto, eu não conseguia entender. Alguém pode explicar:
- qual é a maneira recomendada de usá-lo?
- que finalidade isso resolve?
Para o meu exemplo, aqui estão as minhas aulas com anotações:
Airline
POSSUI muitosAirlineFlights
- Muitos
AirlineFlights
pertencem a UMAirline
Companhia aérea :
@Entity
@Table(name="Airline")
public class Airline {
private Integer idAirline;
private String name;
private String code;
private String aliasName;
private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);
public Airline(){}
public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
setName(name);
setCode(code);
setAliasName(aliasName);
setAirlineFlights(flights);
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="IDAIRLINE", nullable=false)
public Integer getIdAirline() {
return idAirline;
}
private void setIdAirline(Integer idAirline) {
this.idAirline = idAirline;
}
@Column(name="NAME", nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = DAOUtil.convertToDBString(name);
}
@Column(name="CODE", nullable=false, length=3)
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = DAOUtil.convertToDBString(code);
}
@Column(name="ALIAS", nullable=true)
public String getAliasName() {
return aliasName;
}
public void setAliasName(String aliasName) {
if(aliasName != null)
this.aliasName = DAOUtil.convertToDBString(aliasName);
}
@OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
@JoinColumn(name="IDAIRLINE")
public Set<AirlineFlight> getAirlineFlights() {
return airlineFlights;
}
public void setAirlineFlights(Set<AirlineFlight> flights) {
this.airlineFlights = flights;
}
}
Linhas aéreas:
@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
private Integer idAirlineFlight;
private Airline airline;
private String flightNumber;
public AirlineFlight(){}
public AirlineFlight(Airline airline, String flightNumber) {
setAirline(airline);
setFlightNumber(flightNumber);
}
@Id
@GeneratedValue(generator="identity")
@GenericGenerator(name="identity", strategy="identity")
@Column(name="IDAIRLINEFLIGHT", nullable=false)
public Integer getIdAirlineFlight() {
return idAirlineFlight;
}
private void setIdAirlineFlight(Integer idAirlineFlight) {
this.idAirlineFlight = idAirlineFlight;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="IDAIRLINE", nullable=false)
public Airline getAirline() {
return airline;
}
public void setAirline(Airline airline) {
this.airline = airline;
}
@Column(name="FLIGHTNUMBER", nullable=false)
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = DAOUtil.convertToDBString(flightNumber);
}
}
EDITAR:
Esquema do banco de dados:
AirlineFlights possui o idAirline como ForeignKey e Airline não possui o idAirlineFlights. Isso faz com que o AirlineFlights seja o proprietário / entidade de identificação?
Teoricamente, eu gostaria que a companhia aérea fosse a proprietária da companhia aérea.
fonte
@ManyToOne
lado, certo?Os sinais MappedBy hibernam que a chave do relacionamento está do outro lado.
Isso significa que, embora você vincule duas tabelas, apenas uma dessas tabelas possui uma restrição de chave estrangeira para a outra. MappedBy permite que você ainda faça um link da tabela que não contém a restrição para a outra tabela.
fonte
mappedBy
vez de definir, uma bidirecional (com restrições de chave estrangeira em cada lado)?mappedby
fala por si, diz ao hibernate para não mapear este campo. já está mapeado por este campo [name = "field"].campo está na outra entidade
(name of the variable in the class not the table in the database)
..portanto, precisamos dizer ao hibernate para fazer o mapeamento apenas de um lado e coordenar entre eles.
fonte
mappedBy
einversedBy
. Outros ORMs usar muito mais inteligentesbelongsToMany
,hasMany
atributos.mappedby = "objeto de entidade da mesma classe criada em outra classe”
Nota: -Mapped by pode ser usado apenas em uma classe porque uma tabela deve conter restrição de chave estrangeira. se mapeado por puder ser aplicado em ambos os lados, ele removerá a chave estrangeira da tabela e sem a chave estrangeira, não haverá relação entre duas tabelas.
Nota: - pode ser usado para as seguintes anotações: - 1. @ OneTone 2. @ OneToMany 3. @ ManyToMany
Nota --- Não pode ser usado para a seguinte anotação: - 1. @ ManyToOne
Em um para um: - Execute em qualquer lado do mapeamento, mas em apenas um lado. Ele removerá a coluna extra de restrição de chave estrangeira na tabela em que classe é aplicada.
Por exemplo. Se aplicarmos mapeado por na classe Employee no objeto employee, a chave estrangeira da tabela Employee será removida.
fonte
Relacionamento de tabela vs. relacionamento de entidade
Em um sistema de banco de dados relacional, um
one-to-many
relacionamento de tabela é o seguinte:Observe que o relacionamento é baseado na coluna Chave estrangeira (por exemplo,
post_id
) na tabela filha.Portanto, existe uma única fonte de verdade quando se trata de gerenciar um
one-to-many
relacionamento de tabela.Agora, se você usar um relacionamento de entidade bidirecional que mapeie o
one-to-many
relacionamento de tabela que vimos anteriormente:Se você der uma olhada no diagrama acima, poderá ver que existem duas maneiras de gerenciar esse relacionamento.
Na
Post
entidade, você tem acomments
coleção:E, no
PostComment
, apost
associação é mapeada da seguinte maneira:Como existem duas maneiras de representar a coluna Chave Externa, você deve definir qual é a fonte da verdade quando se trata de converter a alteração do estado da associação em sua modificação equivalente no valor da coluna Chave Externa.
MappedBy
O
mappedBy
atributo informa que o@ManyToOne
lado é responsável pelo gerenciamento da coluna Chave Externa, e a coleção é usada apenas para buscar as entidades filhas e fazer cascata de alterações no estado da entidade pai para filhos (por exemplo, remover o pai também deve remover as entidades filho).Sincronize os dois lados de uma associação bidirecional
Agora, mesmo se você definiu o
mappedBy
atributo e a@ManyToOne
associação do lado filho gerencia a coluna Chave Externa, ainda é necessário sincronizar os dois lados da associação bidirecional.A melhor maneira de fazer isso é adicionar esses dois métodos utilitários:
Os métodos
addComment
eremoveComment
garantem que ambos os lados estejam sincronizados. Portanto, se adicionarmos uma entidade filha, a entidade filha precisará apontar para o pai e a entidade pai deverá ter o filho contido na coleção filho.fonte
Você começou com o mapeamento ManyToOne e, em seguida, colocou o mapeamento OneToMany para o modo bidirecional. Então, no lado OneToMany (geralmente sua tabela / classe pai), você deve mencionar "mappedBy" (o mapeamento é feito por e na tabela / classe filho), para que o hibernate não crie uma tabela de mapeamento EXTRA no DB (como TableName = parent_child).
fonte