[Primefaces] Spring - Data - JPA
Bonjour à tous le monde,
Je vais essayer d’être claire.
J'ai diviser mon projet en plusieurs modules Maven qui ont tous un père.
J'ai bcp de classe POJO et autant en repositoty (qui implemente JpaRepository de Spring-Data-Jpa) et autant de classes avec les services et les controllers.
Voici un exemple de ce que j'ai fait .
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Table(name = "address")
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String streetNumber;
private String streetName;
private String city;
private String postalCode;
@ManyToOne
private Country country;
private String website;
private String mail;
private String tel_1;
private String tel_2;
private String fax_1;
private String fax_2;
public Address() {
super();
} |
voici la classe repository AddressRepository
Code:
1 2 3 4 5 6 7 8 9
|
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.repository.annotation.RestResource;
import com.entities.Address;
@RestResource(rel="address", path="address")
public interface AddressRepository extends JpaRepository<Address, Integer>{
} |
mon service .
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import interfaces.IAddressService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.entities.Address;
import dto.AddressDTO;
@Service
@Transactional
public class AddressService extends GenericServiceImpl<Address, AddressDTO, Long> implements IAddressService{
} |
La classe GenericServiceImpl
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package services;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
public class GenericServiceImpl<T, D, ID extends Serializable> implements GenericService<T, D, ID> {
@Autowired
private JpaRepository<T, ID> repository;
@Autowired
private DozerBeanMapper mapper;
protected Class<T> entityClass;
protected Class<D> dtoClass;
@SuppressWarnings("unchecked")
public GenericServiceImpl() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
this.dtoClass = (Class<D>) genericSuperclass.getActualTypeArguments()[1];
}
public D findOne(ID id) {
return mapper.map(repository.findOne(id), dtoClass);
}
public List<D> findAll() {
List<D> result = new ArrayList<D>();
for (T t : repository.findAll()) {
result.add(mapper.map(t, dtoClass));
}
return result;
}
public void save(D dto) {
repository.saveAndFlush(mapper.map(dto, entityClass));
}
public void removeById(int id) {
repository.delete(mapper.map(id, entityClass));
}
} |
La classe GenericService
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| import java.io.Serializable;
import java.util.List;
public interface GenericService <T, D, ID extends Serializable>{
D findOne(ID id);
List<D> findAll();
void save(D dto);
} |
mon autre IAddressService
Code:
1 2 3 4 5 6 7 8 9
| import services.GenericService;
import com.entities.Address;
import dto.AddressDTO;
public interface IAddressService extends GenericService<Address, AddressDTO, Long> {
} |
la classe AddressController
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import services.AddressService;
import dto.AddressDTO;
@Named(value = "addressController")
@ViewScoped
public class AddressController extends AbstractController<AddressDTO> {
@Inject
AddressService addressService;
} |
La classe AbstractController
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import java.util.Collection;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJBException;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import controller.util.JsfUtil;
public abstract class AbstractController<T> {
@Inject
private AbstractFacade<T> ejbFacade;
private Class<T> itemClass;
private T selected;
private Collection<T> items;
private enum PersistAction {
CREATE,
DELETE,
UPDATE
}
public AbstractController() {
}
public AbstractController(Class<T> itemClass) {
this.itemClass = itemClass;
}
/**
* Retrieve the currently selected item
*
* @return
*/
public T getSelected() {
return selected;
}
/**
* Pass in the currently selected item
*
* @param selected
*/
public void setSelected(T selected) {
this.selected = selected;
} |
La classe AbstractFacade
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
} |
Mon probleme c'est que j'ai recuperé ce bout de code sur le net(AbstractController et AbstractFacade) et je voudrai l'adapter au mien.
La classe AbstractFacade j'en ai besoin dans mon projet? car Spring-data fait deja ce genre de chose.
Comment faire que spring-data rentre en jeu?
comme vous l'avez remarqué le but est de factoriser le code car j'ai bcp de classes.
c'est pourquoi j'ai les classes abstraites et des interfaces a chaque couche(Controller, service ou repository).
Je precise aussi que j'ai une autre couche paralelle au POJO qui est DTO afin de sortir de contexte de persistance mes POJO.
Donc mes DTO sont la copie conforme de mes POJO mais sans les annotations.
et si vous avez des ameliorations par rapport a l'architecture je suis prenant.
Ce que je voudrai au final est de faire le CRUD via une seul interface pour tous les controllers.
Merci
Cordialement