GenericDAO inheritance from interface - java

I have an abstract DAO:
public abstract class AbstractJpaDAO<T extends Serializable> implements I_AbstractJpaDAO<T> {
private Class<T> clazz;
#PersistenceContext
protected EntityManager entityManager;
public final void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
#Override
public T findOne(final long id) {
return entityManager.find(clazz, id);
}
#Override
public List<T> findAll() {
return entityManager.createQuery("from " + clazz.getName()).getResultList();
}
#Override
public void create(final T entity) {
entityManager.persist(entity);
}
#Override
public T update(final T entity) {
return entityManager.merge(entity);
}
#Override
public void delete(final T entity) {
entityManager.remove(entity);
}
#Override
public void deleteById(final long entityId) {
final T entity = findOne(entityId);
delete(entity);
}
}
I then extend this DAO in each DAO implementation (code not included) but header something like:
public class UserDAOImpl extends AbstractJpaDAO <User> implements UserDAO {
.....
With each entity, I work with a base interface type, for this example,let's call it UserDAO, and have an associated implementation, let's call it, UserDAOIMPL. To avoid having to define the same methods each Interface to each DAO. As in this longwinded example, i.e :
public interface UserDAO {
User findOne(long id);
List<User> findAll();
void create(User user);
User update(User user);
void delete(User user);
void deleteById(long userID);
User findUserByUserName(String name);
EntityManager returnEntityManager();
}
I would like to instead create a base interface, that all DAOs can extend.
public interface I_AbstractJpaDAO<T> {
.....
}
and then use this in each DAO interface.
public interface userDAO extends I_AbstractJpaDAO<T> { .....
However, I'm getting problems with "both methods have erasure, but neither overrides the other". Something to do with the Serialization thing I suspect. Can anyone help me please?

It means that, your base interface and abstract interface have the methods with the same signature and different return type.
Try this:
public interface userDAO extends I_AbstractJpaDAO<User> { .....

Related

SpringBoot: create object from generic type in generic mapper

I have a lot of entity extend Catalog entity and as well as have a lot of dto that extent CatalogDto
And I have a generic repository, service, and mapper as follows
My repository:
#Repository
public interface CatalogRepository<T extends Catalog> extends JpaRepository<T, Integer>{
}
My service:
#Service
#Transactional
public class CatalogServiceImpl<T extends Catalog,Dto extends CatalogDto>{
private final Logger log = LoggerFactory.getLogger(CatalogServiceImpl.class);
private final CatalogRepository<T> repository;
private CatalogMapper<T,Dto> catalogMapper=new CatalogMapper<T,Dto>() {};
public CatalogServiceImpl(CatalogRepository<T> repository) {
this.repository = repository;
}
}
My Mapper:
public abstract class CatalogMapper<T extends Catalog,Dto extends CatalogDto> implements Rapper<T,Dto> {
#Override
public Dto entityToDto(T entity) {
return null;
}
#Override
public T dtoToEntity(Dto dto) {
return null;
}
}
I want to create an object from T in dtoToEntity method and an object from Dto in entityToDto method in CatalogMapper class
I think that these two methods should be abstract because every mapper probably works in different ways. Anyway you can provide a base implementation like this
public T dtoToEntity(Dto dto) throws InstantiationException, IllegalAccessException {
T entity = (T) ((Class)((ParameterizedType)this.getClass().
getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
BeanUtils.copyProperties(dto, entity);
return entity;
}
public Dto entityToDto(T entity) throws InstantiationException, IllegalAccessException {
Dto dto = (Dto) ((Class)((ParameterizedType)this.getClass().
getGenericSuperclass()).getActualTypeArguments()[1]).newInstance();
BeanUtils.copyProperties(entity, dto);
return dto;
}
Using ParameterizedType of the generic class you can create a new instance and then execute a simple copyProperties

How to create a MongoDB DAO layer like JPA using the entity manager does to facilitate all other DAO class in term of design?

Knowing that there are some frameworks to do it in real-world situation. As I learning from scratch, I wonder is that possible to create pure MongoDB DAO as a layer on top of the Service class to do CRUD operation that also facilitate other DAO use it?
For example, below is my Generic DAO class to operate CRUD process.
public interface IGenericDAO<T> {
public T create(T t);
public T update(T t);
public T get(Object id);
public void delete(Object id);
public List<T> listAll();
public Long count();
}
Then, DAO class should implements its operations
public class UserDAO implements IGenericDAO<User> {
MongoDatabase database = dBUtils.getMongoDB();
MongoCollection <Document> userTbl = database.getCollection("User");
public UserDAO() {
super();
}
#Override
public User create(User user) {
return user;
}
// other CURD below
}
User Service class
public class UserService {
private UserDAO userDAO;
public UserService() {
}
public void listUser() {
// need to test
List<User> listUsers = userDAO.listAll();
}
public void create(User user) {
// this what I want to see. user is saved to db here
try {
MongoDatabase database = dBUtils.getMongoDB();
assert mdb != null;
// create or get collection
MongoCollection<User> userTbl = database.getCollection("Users", User.class);
User userDoc = new User();
userTbl.insertOne(userDoc);
} catch (Exception e) {
e.printStackTrace();
}
}
Having said that, I want to put MongoDB "layer" between the DAO and Service class to do the CRUD operation. I wonder is it necessary, otherwise, how to do it to help the UserService with UserDAO class?

How to test generic abstract class with #Autowired fields?

I have generic abstract class AbstractBaseEntityGenericDao which contains #Autowired field. It worked perfectly until I had to write a unit test for it, to not duplicate the same code inside all tests for classes which extends it. And now I'm thinking...Is it possible to write a unit/integration test for such class?
#Repository
#Transactional
public abstract class AbstractBaseEntityGenericDao<T extends BaseEntity> {
private Class<T> classInstance;
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public final void setClassInstance(Class<T> clasInstance) {
this.classInstance = clasInstance;
}
public void create(#NonNull T entity) {
Session session = sessionFactory.getCurrentSession();
session.save(entity);
}
public Optional<T> find(long id) {
Session session = sessionFactory.getCurrentSession();
return Optional.ofNullable(session.get(classInstance, id));
}
public void update(#NonNull T entity) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(entity);
}
public void remove(#NonNull Long id) throws EntityNotFoundException {
Session session = sessionFactory.getCurrentSession();
session.remove(session.load(classInstance, id));
}
public void remove(#NonNull T entity) {
Session session = sessionFactory.getCurrentSession();
session.remove(entity);
}
}
The reason this is difficult is because generally you should not be doing this. The abstract class should have no knowledge of how its child creates SessionFactory. so instead it should look something like:
#Repository
#Transactional
public abstract class AbstractBaseEntityGenericDao<T extends BaseEntity> {
...
protected SessionFactory sessionFactory;
...
}
Now you CANNOT directly unit test a abstract class as it can not be instantiated. you can however stub it out in a unit test, and test that stub. The stub in turn will have a constructor for the protected field which we can mock out in the unit test. In the end it would look like:
public class AbstractBaseEntityGenericDaoTest {
private class AbstractClassStub extends AbstractBaseEntityGenericDao {
public AbstractClassStub(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void create(BaseEntity entity) {
super.create(entity);
}
#Override
public Optional find(long id) {
return super.find(id);
}
#Override
public void update(BaseEntity entity) {
super.update(entity);
}
#Override
public void remove(#NonNull Long id) throws EntityNotFoundException {
super.remove(id);
}
#Override
public void remove(BaseEntity entity) {
super.remove(entity);
}
}
#Mock
SessionFactory sessionFactory;
private AbstractClassStub abstractClassStub;
#Before
public void before() {
sessionFactory = mock(SessionFactory.class);
abstractClassStub = new AbstractClassStub(sessionFactory);
}
#Test
public void testWhatever() {
abstractClassStub.find(1); //or whatever
}
}

How to implement a generic service class in java Spring Boot?

I have many services that have repeated code and I want to know how to implement a generic service so all my services can extend it.
Service interfaces example (Repeated code):
#Service
public interface IUserService{
List<User> findAll();
User save(User entity);
User findById(long id);
void delete(User entity);
void deleteById(long id);
long count();
}
#Service
public interface IEventService{
List<Event> findAll();
Event save(Event entity);
Event findById(long id);
void delete(Event entity);
void deleteById(long id);
long count();
}
And their implementations (Now, I have the same code in all the implementations):
#Service
public class EventService implements IEventService{
#Autowired
private IEventDao dao;
#Override
public List<Event> findAll() {
return dao.findAll();
}
#Override
public Event save(Event entity) {
return dao.save(entity);
}
Other CRUD methods...
}
#Service
public class UserService implements IUserService{
#Autowired
private IUserDao dao;
#Override
public List<User> findAll() {
return dao.findAll();
}
#Override
public User save(User entity) {
return dao.save(entity);
}
Other CRUD methods...
}
This is fairly straightforward using Java generics. You can replace the actual class User, Event, etc. with a type parameter.
public interface IGenericService<T> {
List<T> findAll();
T save(T entity);
T findById(long id);
void delete(T entity);
void deleteById(long id);
long count();
}
Then do the same for the implementation:
public class GenericService<T> implements IGenericService<T> {
// The DAO class will also need to be generic,
// so that it can use the right class types
#Autowired
private IDao<T> dao;
#Override
public List<T> findAll() {
return dao.findAll();
}
#Override
public T save(T entity) {
return dao.save(entity);
}
// Other CRUD methods...
}
Even further, you can also create your actual services as:
#Service
class UserService extends GenericService<User> { }
#Service
class EventService extends GenericService<Event> { }
Here's a good tutorial from the Java documentation: Learning the Java Language: Generics
Another one with good examples: The Basics of Java Generics

Writing a new dao. No Hibernate Session bound to thread

So I have such classes
BaseDao
public interface BaseDao<T> {
T save(T entity);
}
UserDao
public interface UserDao extends BaseDao<User> {
User getUserByUserName(String name);
}
GenericDao
public abstract class GenericDao implements BaseDao {
#Autowired
protected SessionFactory sessionFactory;
private Class<?> getEntityClass() {
return ((Class) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0]);
}
public T save(T entity) {
Integer id = (Integer) sessionFactory.getCurrentSession().save(entity);
return (T) sessionFactory.getCurrentSession().get(getEntityClass(), id);
}
}
UserDaoImpl
#Repository
public class PgUserDaoImpl extends GenericDao<User> implements UserDao {
public User getUserByUserName(String name) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
User.class);
criteria.add(Restrictions.eq("name", name));
return (User) criteria.uniqueResult();
}
}
GenericService
public class GenericService<T extends GenericDao<E>, E> {
protected T dao;
public GenericService(T dao) {
setDao(dao);
}
#Transactional
public E save(E entity) {
return dao.save(entity);
}
}
UserServiceImpl
#Service("userServiceImpl")
public class UserServiceImpl extends GenericService<PgUserDaoImpl, User>
implements UserService {
#Autowired
public UserServiceImpl(PgUserDaoImpl dao) {
super(dao);
}
#Autowired
private UserAssebmler assebmler;
#Transactional
#Override
public UserDetails loadUserByUsername(String name)
throws UsernameNotFoundException {
.....
}
}
So I write test contoller to save user, but I always get Exception
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
The contoller
#
Controller
#RequestMapping(value = "/test")
public class TestController {
#Autowired
private UserServiceImpl userService;
#RequestMapping(value = "save", method = RequestMethod.GET)
public String test() {
User user = new User();
user.setName("admin");
user.setPassword("21232f297a57a5a743894a0e4a801fc3");
user.setRole(UserRole.ADMIN);
userService.save(user);
return "home";
}
}
Anybody know hot to fix that? Thanks :)
I've solved my question by extending GenericDao class from HibernateDaoSupport class.

Categories

Resources