Uni-directional Onetomany mapping with 3 classes using 1 single class

Asked

Viewed 536 times

0

Good night,

I have the following structure:

@Entity
public class Endereco {
   private String logradouro;
   private String numero;
   private String cep;
   private String bairro;
   private String complemento;
}

@Entity
public class Cliente {
    @OneToMany
    private Set<Endereco> enderecos;
    // Outros atributos...
}

@Entity
public class Fornecedor {
    @OneToMany
    private Set<Endereco> enderecos;
    // Outros atributos...
}

@Entity
public class Procurador {
    @OneToMany
    private Set<Endereco> enderecos;
    // Outros atributos...
}

@Entity
public class Fiador {
    @OneToMany
    private Set<Endereco> enderecos;
    // Outros atributos...
}

How should I create a relationship so that all Customer, Supplier, Attorney and Guarantor classes use the same "ADDRESSES" table or something similar?

  • What’s wrong with the code you posted?

  • So I don’t know if that’s good, in endereco would have to have a key composed Primary key where the relation code and another field that has the information from where that code comes from. Imagine you have only one relation field per primary key at a time the same vendor id may clash with any other causing errors. If it were to make a test Address.Code and Address.Entity where the generated Id comes along with the name of the sender (Guarantor or or Proxy or Supplier or Customer) can even simplify putting letters, it would be a way!

  • You need to have a unique code for your classes, which will be your Primary Keys in the database. Address needs an id. Avoid using composite keys when using a ORM. They all work best with unique ids, although some support composite keys. Ensure referential integrity with constraints, but always add a column that will be the composite key, or the "Object Id". As I don’t use much jpa I don’t know if the @Entity annotation already adds an Id. If so, it’s already solved, no?

  • Once the id problem is solved, your address can be referenced by the other classes in this way. The FK (Foreign Key) will be in the tables referencing address, so different tables can reference the address ID field to ensure referential integrity. With this modeling, you can even share the same address with different entities.

  • I think the most object-oriented way I’ve thought of so far is to create an intermediate class that contains a list of common addresses and attributes among the classes up there and, by persisting addresses in the database, i before persist this class which passes as foreign key its id in a column in the address table. So there will be no duplicate id in both the Customer class and the Address class and I will know how many Addresses there are in each Customer, Guarantor, Vendor and Proxy class. I accept suggestions about this my solution.

  • @andref The problem is that I don’t want to create an auxiliary table (@Jointable) for each entity relating to addresses.

Show 1 more comment

1 answer

0


If you don’t want auxiliary tables (Join table), it is necessary to use inheritance and register the foreign key in the table Endereco. The superclass would be something like:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class ObjetoComEndereco {
    @Id
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy="objetoComEndereco")
    private List<Endereco> enderecos = Lists.newArrayList();
}

Note that the mappedBy is required. If not used, Hibernate will create an auxiliary table and use UNION to recover addresses.

The other classes extend ObjetoComEndereco. For example:

@Entity
public class Cliente extends ObjetoComEndereco {
    // Outros atributos...
}

The class Endereco mute to:

@Entity
public class Endereco {
    @Id
    private Long id;

    @ManyToOne
    private ObjetoComEndereco objetoComEndereco;
}

Hibernate will create only 5 tables:

create table cliente (
    id bigint not null,
    primary key (id)
)

create table endereco (
    id bigint not null,
    objeto_com_endereco_id bigint,
    primary key (id)
)

create table fiador (
    id bigint not null,
    primary key (id)
)

create table fornecedor (
    id bigint not null,
    primary key (id)
)

create table procurador (
    id bigint not null,
    primary key (id)
)

A query by proxy, for example, produces this SQL:

/* criteria query */ select
    this_.id as id1_4_0_,
from
    procurador this_

How the address list is Lazy, Hibernate makes another query when accessing it:

select
    enderecos0_.objeto_com_endereco_id as objeto_c2_1_0_,
    enderecos0_.id as id1_1_0_,
    enderecos0_.id as id1_1_1_,
    enderecos0_.objeto_com_endereco_id as objeto_c2_1_1_ 
from
    endereco enderecos0_ 
where
    enderecos0_.objeto_com_endereco_id=?

If she goes ager the query changes to:

/* criteria query */ select
    this_.id as id1_4_1_,
    enderecos2_.objeto_com_endereco_id as objeto_c2_1_3_,
    enderecos2_.id as id1_1_3_,
    enderecos2_.id as id1_1_0_,
    enderecos2_.objeto_com_endereco_id as objeto_c2_1_0_ 
from
    procurador this_ 
left outer join
    endereco enderecos2_ 
        on this_.id=enderecos2_.objeto_com_endereco_id
  • Solved my problem, thanks @andref!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.