Associação Polimórfica com JPA

leandross

Leandro Sampaio

Posted on April 1, 2021

Associação Polimórfica com JPA

https://thorben-janssen.com/polymorphic-association-mappings-of-independent-classes/
já vou deixar um salve pro Thorben Janssen autor da postagem acima.

Vou fazer um rascunho desse post, e depois vou evoluindo o assunto rs

A questão é que vi e usei dessa abordagem de uma forma não tão bonita quanto essa do post acima e acho que é até uma case comum no mundo corporativo e como achei a abordagem um tanto complexa, achei que poderia adicionar alguns exemplos, e fazer uma versão minha 😅.

Aqui a base em comum

Basicamente marcamos em algumas tabelas as seguintes colunas ORIGEM_KEY e TIPO_ORIGEM_KEY ambas numéricas (essa parte já estava na empresa quando eu cheguei 😅, no caso teria usado um Enum para a representação de tipo).

Fazíamos isso pois em determinado momento do workflow chegavamos em um funil onde basicamente todas as operações do sistema tinham que ser mapeadas e registradas em um "livro". Contudo em determinados momentos precisamos fazer uma "engenharia reversa" do processo para chegar a origem do registro que poderia ser de qualquer parte do sistema.

Obs: Ai vai a primeira desvantagem do modelo, tem que se quebrar uma das regras de normalização do banco (caso você esteja trabalhando com banco relacional) pois quem vai demarcar a origem ou seja a tabela que contém as informações que em teoria estariam vinculadas via uma FK vai TIPO_ORIGEM_KEY e o registro como é dedutivel será de responsabilidade da ORIGEM_KEY. Você pode vir a adicionar CONSTRAINTS para tentar garantir o mínimo de digamos "consistência" contudo a aplicação que terá que fazer todo o trabalho.

Aqui como costumava usar

@Entity
public class ChessPlayer {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
        generator = "chess_player_seq")
    @SequenceGenerator(name = "chess_player_seq",
        sequenceName = "chess_player_seq", initialValue = 100)
    private Long id;

    private String firstName;

    private String lastName;

    private Integer wins;

    private Integer loses;

    ...
}
Enter fullscreen mode Exit fullscreen mode

A partir do tipo salvo fica fácil de implementar uma regra que saiba buscar as demais informações necessárias para a sua necessidade. Contudo da minha forma ainda era um cenário verboso e cheios de IFs...

Em contra partida a versão menos verbosa não é tão flexível e na minha opinião torna o código mais acoplado (isso aqui já é minha conclusão).

public enum TipoOrigem {

  TIPO_1(1,Repository1.class), TIPO_2(2,Repository2.class);

  private final int key;
  private final Class<T> clazz;

  public TipoOrigem(int key ,Class<T extends Repository> clazz){
    key = key;
    clazz = clazz
  }

  public static Map<Integer, Class<T extends Repository>> getMap(){
    return ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Coloquei uma exemplificação que precisa ser melhorada Rs
Mas basicamente segue uma strategy que tem como base a key da relação como chave de seleção.

A partir dela podemos buscar a informação de onde acharmos conveniente.

💖 💪 🙅 🚩
leandross
Leandro Sampaio

Posted on April 1, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related