Architecure disaccoppiata tra livelli aziendali e dati in Spring JPA / Hibernate

0

Sto usando Spring Boot con JPA / Hibernate e sto cercando di disaccoppiare il livello aziendale dal livello dati. Mi piacerebbe essere in grado (relativamente facilmente) di passare da un database relazionale a un triplo store rdf.

Ecco una descrizione semplificata parziale del mio tentativo corrente. Ho entità come:

@Entity(name="Drawer")
public class DrawerEntity {
    @Id
    private int id;
    private String label;

    public int getId(){return id;}
    public void setId(int id){this.id=id;}

    public String getLabel(){return label;}
    public void setLabel(String label){this.label=label;}

}

Ho oggetti business che fungono da proxy per entità come:

public class Drawer{
    @Autowired
    private CardRepository cardRepository;
    private DrawerEntity drawerEntity;

    public Drawer(){this.drawerEntity = new DrawerEntity();}
    public Drawer(DrawerEntity drawerEntity){this.drawerEntity = drawerEntity;}

    public int getId(){return drawerEntity.getId();}
    public void setId(int id){drawerEntity.setId(id);}

    public String getLabel(){return drawerEntity.getLabel();}
    public void setLabel(String label){drawerEntity.setLabel(label);}

    public int getNumberOfCards(){return cardRepository.countByDrawerId(this.getId());}
}

Ho anche un livello di servizio:

public interface DrawerService {
    Collection<Drawer> findAll();
    Drawer findOne(int id);
    Drawer create(Drawer drawer);
    void delete(int id);   
}

Implementato da DrawerServiceBean

@Service
public class DrawerServiceBean implements DrawerService {

    @Autowired
    private DrawerRepository drawerRepository;

    @Override
    public Collection<Drawer> findAll() {
        Collection<Drawer> allCard = new ArrayList<>();
        for(DrawerEntity drawerEntity : drawerRepository.findAll()){
           allCard.add(new Drawer(drawerEntity)); 
        }
        return allCard;
    }

    @Override
    public Drawer findOne(int id) {return new Drawer(drawerRepository.findOne(id));}

    @Override
    public Drawer create(Drawer drawer) {return new Drawer(drawerRepository.save(drawer.getDrawerEntity()));}

    @Override
    public void delete(int id) {drawerRepository.delete(id);}
}

Che è collegato a un repository JPA

@Repository
public interface DrawerRepository extends JpaRepository<DrawerEntity, Integer> {}

Seguendo i consigli forniti in questa risposta , non sto iniettando nulla nelle entità e sto usando business oggetti proxy. Ma poi, sembra che devo usare @Configurable e AspectJ LTW per l'iniezione dei repository negli oggetti business perché "< a href="http://docs.spring.io/autorepo/docs/spring/4.3.x/spring-framework-reference/html/aop.html#aop-pointcuts"> Spring AOP supporta solo i punti di join dell'esecuzione del metodo per Fagioli primaverili ".

L'obiettivo di questa architettura era di essere in grado di definire metodi come getNumberOfCards negli oggetti business che utilizzano diversi tipi di repository ( CardRepository , DrawerRepository ). Ma il risultato sembra complesso con un sacco di codice boilerplate. Mi chiedo come posso semplificare questo? È necessaria la programmazione orientata agli aspetti? Posso ridurre la dimensione del codice boilerplate? Esistono alcune soluzioni fornite da Spring Data?

    
posta Ortomala Lokni 12.09.2016 - 15:38
fonte

1 risposta

1

Qualche tempo fa, ho chiesto a SO una domanda che includesse if i devo implementare il mio servizio poiché utilizzano entità gestite JPA? Ecco i due punti della mia risposta che dovrebbero interessarti:

  • I don't have to abstract the fact that i use managed entities, this will lead to complex and unefficient code

  • I choosed JPA, i won't switch for it which is true unless rewriting the full model to stand for something based on non relationnal database.

Se tenti di astrarre il fatto che stai usando entità pigri / gestite, avrai solo problemi. Ad esempio, ho visto un progetto in cui erano presenti DAO Pojo e business POJO, convertendo sempre DAO in business POJO tramite adattatore, e quindi attivando sempre il caricamento di lazy list nel modo di selezione N + 1.

Quindi, se adattare quello che mi è stato detto in questa domanda, per lo meno, dovresti avere 2 implementazioni aziendali differenti, una basata sulla forza di JPA, e l'altra, o una che non si preoccupa di JPA / RDF, uno che otterrà il meglio del livello DAO RDF.

So che non sembra seguire la regola di POO sul comportamento totalmente incapsulante in ogni livello, ma in realtà, prova ad astrarre il modello JPA complesso senza attivare la selezione N + 1 a cascata su ogni relazione o recuperando manualmente ogni relazione quando non dovrebbe essere necessario con JPA. Non può funzionare. JPA è davvero invasivo, ma anche molto potente, dato che hai pochissimo codice da scrivere (e mantenere!) Per usarlo.

Ovviamente se stai semplicemente facendo qualcosa di veramente semplice avendo pochi dati, una demo, ... puoi aderire a un livello aziendale che non usa il JPA al suo meglio.

Ma se hai bisogno di alcune prestazioni di base, come caricare tutto il tuo database riga per riga nell'ORM non è un'opzione, probabilmente finirai con un'attuazione che non usa il diritto JPA.

    
risposta data 13.09.2016 - 14:56
fonte

Leggi altre domande sui tag