DEV Community

Leandro Sampaio
Leandro Sampaio

Posted on

2 2

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.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay