Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it necessary to create an repository and a service for each entity? [duplicate]

I'm using Hibernate+Spring and a database to persist my entities. I'm already using JpaRepository to create my repositories but even then, it seems I must create one interface extending JpaRepository for each entity. Worst, I'm creating one service to each entity. All of them very similar.

There's any way to create a generic service and a generic repository? Is it really necessary to implement each one of them?

By the moment, I have repositories like this:

@Repository
public interface PhaseRepository extends JpaRepository<Phase, Serializable> {

}

and services like this:

@Service
public class PhaseService {
    @Autowired
    PhaseRepository repository;

    @Transactional
    public Phase create(Phase entity) {
        return repository.save(entity);
    }

    @Transactional(rollbackFor = EntityNotFound.class)
    public Phase delete(int id) throws EntityNotFound {
        Phase deleted = repository.findOne(id);
        if (deleted == null) {
            throw new EntityNotFound();
        }
        repository.delete(deleted);
        return deleted;
    }

    @Transactional(rollbackFor = EntityNotFound.class)
    public Phase update(Phase entity) throws EntityNotFound {
        Phase updated = repository.findOne(entity.getId());

        if (updated == null) {
            throw new EntityNotFound();
        }

        repository.saveAndFlush(entity);
        return updated;
    }

    public Phase findById(int id) throws EntityNotFound {
        Phase entity = repository.findOne(id);

        if (entity == null) {
            throw new EntityNotFound();
        }

        return entity;
    }
}

I'm using 12 entities and everyone has the same service methods.

Thanks!

like image 722
Leandro Lima Avatar asked Jun 08 '15 20:06

Leandro Lima


People also ask

Should I have a service for each entity?

No. You do not need to create one service for one entity. In DDD you would create services for operations that do not naturally map to a single entity (or value object).

Does every entity need a repository?

It depends on your logic and how "important" are every entity. For example, if you had the entities User and Address you could have UserRepository and AddressRepository. But only UserService, with methods like addAddress(User user, Address address)... Save this answer.

Is it mandatory to use @repository?

It is indeed not necessary to put the @Repository annotation on interfaces that extend JpaRepository ; Spring recognizes the repositories by the fact that they extend one of the predefined Repository interfaces.

Why is repository needed?

A repository provides separation between a domain and a persistent layer. A repository provides an interface to access data stored in the database or external resources. Data is returned in the form of objects. Repositories act as a bridge between the models and the controller.


2 Answers

Probably you'll need the 12 repositories. But maybe you won't need 12 services. A service could handle the access to several repositories. It depends on your logic and how "important" are every entity.

For example, if you had the entities User and Address you could have UserRepository and AddressRepository. But only UserService, with methods like addAddress(User user, Address address)...

All in all, I'd recomend you to organize your services accordingly your business logic instead of a bunch of CRUDs

like image 142
polypiel Avatar answered Oct 26 '22 22:10

polypiel


You need 12 repositories, because Spring initializes instances of your declared interfaces. Spring already did a good job, I don't see a problem here. Imagine a situation back the days, when you had to implement these repositories by boilerplate JDBC code.

But you don't automatically need services for your repositories. Create services for your application purposes and autowire necessary repositories inside them. But I have created an example code, if you want generic service without copy-pasting code:

public abstract class AbstractService<T extends AbstractEntity, K extends Serializable> {

    protected JpaRepository<T, K> repository;

    public AbstractService(final JpaRepository<T, K> repository) {
        this.repository = repository;
    }

    @Transactional(rollbackFor = EntityNotFound.class)
    public T delete(final K id) throws EntityNotFound {
        final T deleted = this.repository.findOne(id);
        if (deleted == null) {
            throw new EntityNotFound();
        }
        this.repository.delete(deleted);
        return deleted;
    }

    ...

}

Implementing class would be:

@Service
public class PhaseService extends AbstractService<PhaseEntity, Integer> {

    @Autowired
    public PhaseService (final PhaseRepository repository) {
        super(repository);
    }

}

Also a few tips:

  • You don't need EntityNotFound exception. Just check if entity is null.
  • Instead of Serializable use primary key strong type - an Integer for example.
like image 40
Gondy Avatar answered Oct 26 '22 22:10

Gondy