JPA and generics, why is my class not working?

In my Spring web application, I use the generic dao class:

public abstract class GenericDaoImpl<T> implements GenericDao<T> {

    @Override
    public T create(final T t) {
        this.getEntityManager().persist(t);
        return t;
    }

    @Override
    public void delete(final Object id) {
        this.getEntityManager().remove(
                this.getEntityManager().getReference(getEntityType(), id));
    }

    @Override
    public T find(final Object id) {
        return (T) this.getEntityManager().find(getEntityType(), id);
    }

    @Override
    public T update(final T t) {
        return this.getEntityManager().merge(t);
    }
}

I implement this class for every object in my model, and it works great. For instance:

@Repository
public class GruppoDaoImpl extends GenericDaoImpl<Gruppo> implements GruppoDao {

}

I use these dao classes in my service. I have a service level for each object in my model, but the methods for most of these classes are the same, so I tried to create a common service class that I can extend in the same way as for a general dao:

public abstract class GenericAdminServiceImpl<ENTITY extends AbstractEntity, DTO extends AbstractDto>
    implements GenericAdminService<ENTITY, DTO> {

    private GenericDao<ENTITY> dao;
    private Class<ENTITY> entityClass;
    private Class<DTO> dtoClass;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected GenericAdminServiceImpl(GenericDao<ENTITY> dao) {
        this.dao = dao;
        //
        Type t = getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) t;
        this.entityClass = (Class) pt.getActualTypeArguments()[0];
        this.dtoClass = (Class) pt.getActualTypeArguments()[1];
    }

    public DTO getById(Object id) {
        DTO dto = null;
        ENTITY entity = dao.find(id);
        if (entity != null) {
            try {
                dto = dtoClass.newInstance();
                initDto(entity, dto);
            } catch (Exception e) {
            }
        }
        return dto;
    }

    public void create(DTO dto) throws ServiceOperationException {
        ENTITY entity;
        try {
            entity = entityClass.newInstance();
            initEntity(dto, entity);
            Date dt = new Date();
            entity.setDataUltimoAggiornamento(dt);
            entity.setUtenteUltimoAggiornamento(dto.getLoggedUser());
            entity.setDataInserimento(dt);
            entity.setUtenteInserimento(dto.getLoggedUser());
            dao.create(entity);
        } catch (Exception e) {
            throw new ServiceOperationException("impossibile creare entity ["
                    + entityClass.getSimpleName() + "]", e);
        }
    }

    public void update(DTO dto) throws ServiceOperationException {
        ENTITY entity = dao.find(dto.getId());
        if (!entityExists(entity)) {
            throw new ServiceOperationException("entity non esistente ["
                    + entityClass.getSimpleName() + "#" + dto.getId() + "]");
        }
        initEntity(dto, entity);
        Date dt = new Date();
        entity.setDataUltimoAggiornamento(dt);
        entity.setUtenteUltimoAggiornamento(dto.getLoggedUser());
        dao.update(entity);
    }

    public void delete(Object id) throws ServiceOperationException {
        try {
            dao.delete((int) id);
        } catch (Exception e) {
            throw new ServiceOperationException(
                    "impossibile eliminare entity ["
                            + entityClass.getSimpleName() + "#" + id + "]", e); // TODO
        }
    }

    protected abstract void initDto(ENTITY entity, DTO outDto);

    protected abstract void initEntity(DTO dto, ENTITY outEntity);

    protected abstract boolean entityExists(ENTITY entity);

}

Extension of this class. I just need to implement specific parts for each object, leaving all the usual things in an abstract / universal class. The problem is that merging, saving and deleting do not work using the common service . It seems that only select works, and I don't understand why ...

Eclipse, . merge/persist, ? ?

# 1

:

@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class GruppoServiceImplG extends
        GenericAdminServiceImpl<Gruppo, GruppoDto> implements GruppoServiceG {

    @Autowired
    protected GruppoServiceImplG(GruppoDao gruppoDao) {
        super(gruppoDao);
    }

    @Override
    protected void initDto(Gruppo entity, GruppoDto outDto) {
        outDto.setId(entity.getId());
        outDto.setNome(entity.getNome());
        outDto.setDescrizione(entity.getDescrizione());
        outDto.setDataInizioValidita(entity.getDataInizioValidita());
        outDto.setDataFineValidita(entity.getDataFineValidita());
    }

    @Override
    protected void initEntity(GruppoDto dto, Gruppo outEntity) {
        outEntity.setId(dto.getId());
        outEntity.setNome(dto.getNome());
        outEntity.setDescrizione(dto.getDescrizione());
        outEntity.setDataInizioValidita(dto.getDataInizioValidita());
        outEntity.setDataFineValidita(dto.getDataFineValidita());
    }

    @Override
    protected boolean entityExists(Gruppo entity) {
        return entity != null && entity.getId() > 0;
    }

}

# 2

Łukasz L., crud a flush(). javax.persistence.TransactionRequiredException: no transaction is in progress. ? -generic serices...

+3
2

Łukasz L., .

. @Transactional(propagation = Propagation.REQUIRES_NEW) .

:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public abstract class GenericAdminServiceImpl<ENTITY extends AbstractEntity, DTO extends AbstractDto>
    implements GenericAdminService<ENTITY, DTO> {

    // ...

}

( ):

@Service
@Transactional
public class GruppoServiceImplG extends
        GenericAdminServiceImpl<Gruppo, GruppoDto> implements GruppoServiceG {

    // ...

}
+1

Spring Hibernate, EntityManager . Spring JPA (Hibernate & CO) ( Spring), , , , .

: JPA . , . SELECT, - ( - , ). INSERT UPDATE - . , create, merge remove , flush() EntityManager.

flush, , , !

EntityManager.flush(), , . DML, ( , , DML- JPA, DB-/, ).

@Transactional
public void myTransactionalMethod() {
  getEntityManager().persist(a); // I've made some JPA change, that is not issued to DB yet
  ...
  // I'm doing something more
  ...
  getEntityManager().flush(); // the last moment to flush, after that instruction I leave transactional context
}
+1

All Articles