Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I keep my Java model independent from JPA entities while avoiding code duplication [closed]

My Java project uses JPA as a persistence solution. As I read more and more JPA tutorials and guides I find (for the sake of simplicity, maybe) that every writer uses the entity classes as their model classes. That's obviously a poor design choice with regards to code extensibility and maintainability: a decision to change the persistence solution would imply a complete refactoring (or rewriting) of the whole model.

Thing is, rewriting model classes corresponding to each entity class feels out of place and inelegant, since the would all just ditto the corresponding entity class (in my personal case), were it not for the JPA annotations. Writing them off as interfaces implemented by the entity classes feels wrong as well, be it for the potential inconsistency arising when I might need to expand the model with a class that does not correspond to an entity, or for the fact that in Java the generics used to represent @OneToMany and @ManyToMany relationships are not (and should not be) covariant with the abstracting interfaces.

I shall now post some code to exemplify my concern:

package com.depvin.pps.orm;

import javax.persistence.*;


@Entity
@DiscriminatorValue("E")
public class EmployeeEntity extends UserEntity {
    @ManyToMany
    @JoinTable(name = "EmployeeProject",
            joinColumns = @JoinColumn(name = "employee"),
            inverseJoinColumns = @JoinColumn(name = "project"))
    List<ProjectEntity> projects;

    public EmployeeEntity(String username) {
        super(username);
    }

    public List<ProjectEntity> getProjects() {
        return projects;
    }
}

How should the corresponding model class/interface be realized, taking into account the matters I brought up above?

like image 425
Michele De Pascalis Avatar asked Sep 07 '25 05:09

Michele De Pascalis


2 Answers

From my point of view it is obvious that it is a good design. An entity is a model class. It is (or should be) the manifestation of the business object which is part of the domain model.

You are right, you should not build your model for the persistence API. But I don't see in the example above where you do that. Except for the annotations, but those don't make up your model, its just metadata. You could even put that into an extra mapping file and would have straight model classes.

If you mean that you create your model classes from an existing database and the resulting classes do not express the business model, then you should think about your database model.

And you can at anytime change the persistence solution, I can't see why you need to stick to JPA here. It would be very easy, for example, to create a JSON from any entity class with just some annotations.

Last thing: JPA is only using the generic type of a collection, if you don't define the targetEntity attribute in the @OneToMany.

like image 153
Tobias Liefke Avatar answered Sep 09 '25 02:09

Tobias Liefke


The annotations of JPA-Objects are object-relational mapping, so JPA-Objects are part of the object-relational mapping.

You are right, that you often see JPA objects as model objects in project architecture. I don't say that this solution is sufficient bad in every situation. But if you want to be clear you should separate the two aspects of object relational mapping layer and business layer. If you have done this, you maybe have technical redundancy but no SEMANTICAL redundancy according to SRP. SRP says that one code fragment should only be change for one purpose. If the mapping changes, then the ORM layer is the right place. If the business rules change go to the model layer.

Of course you may have code to transfer data between the layers. A "String name" may appear in the JPA-Object and in the Model-Object. But its not a mapping at all, its caching. Caching makes the redundancy that makes you uncomfortable. If you don't want to cache, delegate from the model layer to the JPA-Layer. But keep Business logic separated from the JPA-Layer.

After all: if you have a small project you won't face any real problems with a JPAObject-only solution. It all comes with the size. And then I recommend the BusinessObject -> DAO -> JPAObject structure.

like image 30
oopexpert Avatar answered Sep 09 '25 01:09

oopexpert