I am a beginner in Java and in the Spring environment. At the moment I have to implement a CustomerRepository. The CustomerRepository implements a CrudRepository interface. The purpose is that in the repository, customer objects should be stored and retrieved.
I have to use a Mock implementation of the Spring class CrudRepository.
The classdiagram looks like this:
classdiagram
CrudRepository interface:
public interface CrudRepository<Customer, String> {
<S extends Customer> S save( S entity );
...
}
The complete CustomerRepository class:
public class CustomerRepository implements CrudRepository<Customer, String> {
private CrudRepository crudrepository;
/*long count();*/
#Override
public long count() {
long count = crudrepository.count();
return count;
}
/*<S extends Customer> S save( S entity );*/
#Override
public <S extends Customer> S save(S entity) {
crudrepository.save(entity);
return entity;
}
/*<S extends Customer> Iterable<S> saveAll( Iterable<S> entities );*/
#Override
public <S extends Customer> Iterable<S> saveAll(Iterable<S> entities) {
Iterable<S> response = crudrepository.saveAll(entities);
return (Iterable<S>) response;
}
/*Optional<Customer> findById(String id );*/
#Override
public Optional<Customer> findById(String id) {
Optional<Customer> customerResponse = crudrepository.findById(id);
return customerResponse;
}
/*Iterable<Customer> findAllById(Iterable<String> ids );*/
#Override
public Iterable<Customer> findAllById(Iterable<String> ids) {
Iterable<Customer> customerResponse = crudrepository.findAllById(ids);
return customerResponse;
}
/*Iterable<Customer> findAll();*/
#Override
public Iterable<Customer> findAll() {
Iterable<Customer> customerResponse = (Iterable<Customer>) crudrepository
.findAll();
return customerResponse;
}
/*boolean existsById(String id );*/
#Override
public boolean existsById(String id) {
return crudrepository.existsById(id);
}
/*void deleteById(String id );*/
#Override
public void deleteById(String id) {
crudrepository.deleteById(id);
}
/*void delete(Customer entity );*/
#Override
public void delete(Customer entity) {
crudrepository.delete(entity);
}
/*void deleteAllById(Iterable<? extends String> ids );*/
#Override
public void deleteAllById(Iterable<? extends String> entities) {
crudrepository.deleteAll(entities);
}
/*void deleteAll();*/
#Override
public void deleteAll() {
crudrepository.deleteAll();
}
/*void deleteAll(Iterable<? extends Customer> entities );*/
#Override
public void deleteAll(Iterable<? extends Customer> entities) {
crudrepository.deleteAll(entities);
} }
How does that look for you ? Any suggestions ?
I think you are misunderstanding some concepts.
CrudRepository is a Spring object and it's an interface you don't need to implement. You have to extend it and Spring provides you all the magic.
You can achieve your goal simply in the following way:
Repository
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomerRepository extends CrudRepository<Customer, String> {
}
Service
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CustomerService {
#Autowired
private CustomerRepository customerRepository;
public Customer save(Customer customer) {
Customer response = customerRepository.save(customer);
return response;
}
}
Related
I'm playing with a Spring application with 2 controllers and 2 services that manages related entities and I would like to avoid duplicating code. I've got for example a Person class with his PersonRepository
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class Person {
#Id
Long id;
String name;
String surname;
}
And his child User with his UserRepository
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class User extends Person {
String login;
String password;
}
I've a simple Person service whith business logic:
#Service
public class PersonService {
#Autowired
PersonRepository repo;
public Iterable<Person> getAll() {
// Busines Logic
return repo.findAll();
}
}
Is there a way to create a UserService extending or proxying PersonService and implementing some kind of repository "hiding"? Something like this:
#Service
public class UserService extends PersonService {
#Autowired
UserRepository repo;
}
that obviously gives this error:
Type mismatch: cannot convert from Iterable<Person> to Iterable<User> with a controller like this
#RestController
#RequestMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
public class DemoController {
#Autowired
UserService service;
#GetMapping
public void items() {
Iterable<User> persons = service.getAll();
return;
}
}
Try the following structure:
Common service and repository:
#NoRepositoryBean
public interface PersonRepository<T> extends JpaRepository<T, Long> {
}
public class PersonService<T extends Person> {
protected PersonRepository<T> repository;
public <R extends PersonRepository<T>> PersonService(R repository) {
this.repository = repository;
}
public Iterable<T> getAll() {
return repository.findAll();
}
}
For User entity:
public interface UserRepository extends PersonRepository<User> {
}
#Service
public class UserService extends PersonService<User> {
public UserService(UserRepository repository) {
super(repository);
}
public void additionalMethod() {
User user = repository.getOne(1L);
}
}
And I added Company entity by User entity example:
public interface CompanyRepository extends PersonRepository<Company> {
}
#Service
public class CompanyService extends PersonService<Company> {
public CompanyService(CompanyRepository repository) {
super(repository);
}
public void additionalMethod() {
Optional<Company> company = repository.findById(1L);
}
}
I try to implement generic service-layer class for basic CRUD operations.
public abstract class AbstractService<T, R extends JpaRepository> {
protected R repository;
public AbstractService(R repository) {
this.repository = repository;
}
public T getOne(final Long id){
return repository.findById(id); // error Required: T, Found: Optional<>
}
}
Why couldnt I use type T without wrapping it to Optional?
You should always follow the good practices that are recommended for JPA and hibernate, so you must create a respository per entity, as this will allow you to develop more scalable applications, however if you want not to have to do this and want an abstract class that allows you To do this, I recommend doing an abstract Dao class that allows you to perform CRUD operations as follows:
import java.io.Serializable;
import java.util.List;
/**
* #author Edy Huiza
* #version 1.0
* Created on 23/11/2018
*/
public interface Dao<T> {
void persist(Object entity);
void persist(Object[] entities);
void update(Object entity);
void delete(Object entity);
void delete(Class entityClass, Serializable id);
List findAll(Class entityClass);
Object get(Class entityClass, Serializable id);
}
And their respective implementation
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
/**
* #author Edy Huiza
* #version 1.0
* Created on 23/11/2018
*/
#Repository
public class SpringHibernateDao implements Dao {
#PersistenceContext
private EntityManager entityManager;
#Override
#Transactional
public void persist(Object entity) {
entityManager.persist(entity);
entityManager.flush();
entityManager.clear();
}
#Override
#Transactional
public void update(Object entity) {entityManager.merge(entity);
}
#Override
#Transactional
public void persist(Object[] entities) {
for (Object entity : entities) {
persist(entity);
}
}
#Override
#Transactional
public void delete(Object entity) {
entityManager.remove(entity);
}
#Override
#Transactional
public void delete(Class entityClass, Serializable id) {
Object entity = get(entityClass, id);
entityManager.remove(entity);
}
#SuppressWarnings("unchecked")
#Override
#Transactional(readOnly = true)
public List findAll(Class entityClass) {
return entityManager.createQuery("from " + entityClass.getName()).getResultList();
}
#Override
#Transactional(readOnly = true)
public Object get(Class entityClass, Serializable id) {
return entityManager.find(entityClass, id);
}
}
And their respective use
#Autowired
Dao dao;
#Override
#Transactional(readOnly = true)
public Dispositivo get(long id) {
return (Dispositivo) dao.get(Dispositivo.class, id);
}
You can try something like this:
public abstract class AbstractService<T, ID, R extends JpaRepository<T, ID>> {
protected R repository;
public AbstractService(R repository) {
this.repository = repository;
}
public Optional<T> getOne(ID id){
return repository.findById(id);
}
}
I'm using a DAO pattern and Hibernate for my simple JavaFX project for performing CRUD operations. Since I'm new to Hibernate I want to ask you how to implement a particular method.
Firstly I have a solid DAO interface:
import java.util.List;
import org.hibernate.Session;
import java.util.List;
import org.hibernate.Session;
public interface Dao<T, ID> {
public T findById(ID id);
public List<T> findAll();
public T save(T entity);
public void delete(T entity);
public void flush();
public void clear();
public void setSession(Session session);
}
Then I have another interface (more specific):
public interface FotoDao extends Dao<Foto, Integer> {
public List<Foto> findByCarId(Integer id);
}
Followed by another class:
import dao.interfaces.Dao;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import utils.HibernateUtil;
public class AbstractDao<T, ID extends Serializable> implements Dao<T, ID> {
private Class<T> persistentClass;
private Session session;
#SuppressWarnings("unchecked")
public AbstractDao() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public void setSession(Session session) {
this.session = session;
}
protected Session getSession() {
if (this.session == null) {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
return this.session;
}
public Class<T> getPersistentClass() {
return persistentClass;
}
#SuppressWarnings("unchecked")
#Override
public T findById(ID id) {
return (T) getSession().load(this.getPersistentClass(), id);
}
#Override
public List<T> findAll() {
return this.findByCriteria();
}
protected List<T> findByCriteria(Criterion... criterion) {
Criteria crit = this.getSession().createCriteria(this.getPersistentClass());
for (Criterion c : criterion) {
crit.add(c);
}
return (List<T>) crit.list();
}
#Override
public T save(T entity) {
this.getSession().saveOrUpdate(entity);
return entity;
}
#Override
public void delete(T entity) {
this.getSession().delete(entity);
}
#Override
public void flush() {
this.getSession().flush();
}
#Override
public void clear() {
this.getSession().clear();
}
}
Then finally I have a concrete class:
public class FotoHibernateDao extends AbstractDao<Foto, Integer> implements FotoDao {
#Override
public List<Foto> findByCarId(Integer id) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
How do I implement the findByCarId(Integer id) method?
In my data model I have a table which stores foto urls of cars. And I want this
method to return only images associated with a carId (which is a foreign key).
I customizei a repository for all my repositories children have the same methods. The code is below the repository implementation.
This interface:
#NoRepositoryBean
public interface BaseMyRepository<T, ID extends Serializable> extends JpaRepository<T, ID>{
List<T> findCustomNativeQuery(String sqlQuery);
}
This implementation class:
public class BaseMyRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseMyRepository<T, ID>{
private final EntityManager entityManager;
public BaseMyRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager){
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
#Transactional
#Override
public List<T> findCustomNativeQuery(String sqlQuery) {
List<T> lista = entityManager.createNativeQuery(sqlQuery, this.getDomainClass()).getResultList();
return lista;
}
}
This my repository:
public interface MyRepository extends BaseMyRepository<SmaempreEntity, Integer>{
}
Now I need to know if is possible do exemplify the code below:
#Service
#Transactional
public class MyBaseService<R extends BaseMyRepository, E> {
#Autowired
private R;
public List<E> findAll() {
return R.findAll();
}
public List<E> findCustomNativeQuery(String sqlQuery) {
return R.findCustomNativeQuery(sqlQuery);
}
}
public class MyService extends MyBaseService<MyRepository, MyEntity> {
}
I'm implementing GenericDao. I have problem with 2 methods - getAll() and getById(Long id), entity class has null value. It looks like the class is not setted. How Can I solve this problem ?
#Repository
public class GenericDaoImpl<T> implements GenericDao<T> {
private Class<T> clazz;
#Autowired
SessionFactory sessionFactory;
public void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T getById(final Long id) {
return (T) this.getCurrentSession().get(this.clazz, id);
}
public List<T> getAll() {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
this.clazz);
return criteria.list();
}
protected final Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
PersonDao
public interface PersonDao extends GenericDao<Person> { }
PersonDaoImpl
#Repository("PersonDAO")
public class PersonDaoImpl extends GenericDaoImpl<Person> implements PersonDao {}
Service:
#Service
public class PersonServiceImpl implements PersonService {
#Autowired
private PersonDao personDao;
#Transactional
public List<Person> getAll() {
return personDao.getAll();
}
#Transactional
public Person getById(Long id) {
return personDao.getById(id);
}
}
You must set the clazz property of PersonDao. This can be done by declaring a post initialization callback with the #PostConstruct annotation.
#Repository("PersonDAO")
public class PersonDaoImpl extends GenericDaoImpl<Person> implements PersonDao {
#PostConstruct
public void init(){
super.setClazz(Person.class);
}
}