Autowiring a Class<T extends BaseEntity> when Autowiring a DAO bean - java

So I have tried searching all over for this blocker and tried many different ways of finding a solution but I cannot wrap my head around it. I am a beginner in Spring and I have created a generic DAO that takes in any T which extends BaseEntity. I have the following code:
private Class<T> clazz;
#Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
Which I have put inside my BaseDAOImpl. Then I use this constructor:
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
to create a JacksonDbCollection for MongoDB. In my CustomerServiceImpl I Autowire my BaseDAO bean so that I can use my DAO for persistance.
#Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
So when I run a method that uses my BaseDAOImpl, I get a NullPointerException and I am pretty sure it is because of the Class that is not picking up my CustomerEntity. My question is how can I get Class to pick up CustomerEntity when I Autowire my baseDao bean? Or what suggestions do you have for me to solve my problem? I just need a different point of view and thought I would ask for it here.
Thank you in advanced for you assistance.
Update
BaseDAOImpl
package za.co.thekeeper.dao;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import za.co.thekeeper.mongo.MongoDbUtil;
import java.util.ArrayList;
import java.util.List;
#Repository
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class BaseDAOImpl<T extends BaseEntity> implements BaseDAO<T> {
private JacksonDBCollection<T, String> collection;
/**Dependency Injections**/
private MongoConnection mongoConnection;
#Autowired
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
#Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
#Override
public T create(T entity) {
entity.activate();
entity.beforePersist();
WriteResult<T, String> inserted = this.collection.insert(entity);
return inserted.getSavedObject();
}
#Override
public void delete(T entity) {
deactivate(entity);
}
#Override
public T activate(T entity) {
entity.activate();
return update(entity);
}
#Override
public T deactivate(T entity) {
entity.deactivate();
return update(entity);
}
#Override
public void activate(String id) {
T entity = getById(id);
if (entity == null) {
throw new NullPointerException("Entity not found with id: " + id);
}
activate(entity);
}
#Override
public void deactivate(String id) {
T entity = getById(id);
if (entity == null) {
throw new NullPointerException("Entity not found with id: " + id);
}
deactivate(entity);
}
#Override
public T update(T entity) {
entity.beforePersist();
WriteResult<T, String> saved = this.collection.save(entity);
return saved.getSavedObject();
}
#Override
public void deleteById(String id) {
deactivate(id);
update(getById(id));
}
#Override
public T getById(String id) {
return this.collection.findOneById(id);
}
#Override
public List<T> findByField(String field, Object o) {
DBQuery.Query query = DBQuery.is(field, o);
DBCursor<T> cursor = this.collection.find(query);
return readCursor(cursor);
}
#Override
public void createDBRef(String databaseName, String collectionName, String id) {
}
#Override
public List<T> findAll() {
return findByField("activate", Boolean.TRUE);
}
/**
* Cursor
**/
private List<T> readCursor(DBCursor<T> cursor) {
if (cursor.size() > 0) {
List<T> found = new ArrayList<>();
while (cursor.hasNext()) {
found.add(cursor.next());
}
return found;
}
return null;
}
}
CustomerServiceImpl
package za.co.thekeeper.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import za.co.thekeeper.dao.BaseDAO;
import za.co.thekeeper.dao.BaseDAOImpl;
import za.co.thekeeper.entities.CustomerEntity;
import za.co.thekeeper.entities.MerchantEntity;
import za.co.thekeeper.entities.ReceiptEntity;
import za.co.thekeeper.mongo.MongoConnection;
import java.util.List;
import java.util.UUID;
#Service
public class CustomerServiceImpl implements CustomerService {
private BaseDAO<CustomerEntity> baseDAO;
#Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
#Override
public CustomerEntity registerNewCustomer(CustomerEntity customer) {
if (customer.getId() == null) {
customer.setId(UUID.randomUUID().toString());
}
CustomerEntity entity = baseDAO.create(customer);
System.out.println(entity.toString());
return entity;
}
#Override
public CustomerEntity getCustomer(String cellNumber) {
List<CustomerEntity> entities = baseDAO.findByField("cellNumber", cellNumber);
return entities.get(0);
}
#Override
public CustomerEntity updateCustomerDetails(CustomerEntity customer) {
return baseDAO.update(customer);
}
#Override
public void deleteCustomer(CustomerEntity customer) {
baseDAO.delete(customer);
}
}
Application Context
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="za.co.thekeeper"/>
As requested.
New Update
BaseDAO
package za.co.thekeeper.dao;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import java.util.List;
public interface BaseDAO<T extends BaseEntity> {
T create(T entity);
void delete(T entity);
T activate(T entity);
T deactivate(T entity);
void activate(String id);
void deactivate(String id);
T update(T entity);
void deleteById(String id);
T getById(String id);
List<T> findByField(String id, Object o);
void createDBRef(String databaseName, String collectionName, String id);
List<T> findAll();
}

You existing BaseDAOImpl:
private MongoConnection mongoConnection;
#Autowired
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
#Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
This is not the right way to initialize this bean.
You are doing a setter injection on mongoConnection and accessing that in the default constructor. MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz); The constructor gets called before the setter is invoked. This is going to result in NPE.
Nobody is setting the clazz variable.
#Autowired on a setter and #Bean on a getter is meaningless.
#Repository annotation is not required. You can use #Component
The right way to do things would be this.
BaseDAOImpl class - Including only a part of the class for brevity
package za.co.thekeeper.dao;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import za.co.thekeeper.mongo.MongoDbUtil;
import java.util.ArrayList;
import java.util.List;
public class BaseDAOImpl<T extends BaseEntity> implements BaseDAO<T> {
private JacksonDBCollection<T, String> collection;
/**Dependency Injections**/
private MongoConnection mongoConnection;
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl(MongoCollection mongoCollection, Class<T> clazz) {
this.mongoCollection = mongoCollection;
this.clazz = clazz;
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
}
Spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="za.co.thekeeper"/>
<bean class="za.co.thekeeper.dao.BaseDAOImpl">
<constructor-arg index="0" ref="mongoCollection"/>
<constructor-arg index="1">
<value type="java.lang.Class">CustomerEntity</value>
</constructor-arg>
</bean>
Spring will detect the type T from the second constructor injection and allow you to autowire beans of type BaseDAOImpl<CustomerEntity>.
Note: I assume mongoCollection is declared as a spring bean elsewhere. Otherwise you need to add that in the spring configuration file.

private BaseDAO<CustomerEntity> baseDAO;
#Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
Try using constructor-injection instead. Check if it helps
private BaseDAO<CustomerEntity> baseDAO;
#Autowired
public CustomerServiceImpl(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}

Related

Bean property 'sakilaDao' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

I am writing a Spring Program which is working fine with MVC Architecture. But showing the below error after basic spring implementation.
Error creating bean with name 'manager' defined in class path resource [applicationContext.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'SakilaDao' of bean class [com.java.Training.managerImpl.SakilaManagerImpl]: Bean property 'SakilaDao' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dao" class="com.java.Training.DaoImpl.SakilaDaoImpl">
</bean>
<bean id="manager" class="com.java.Training.managerImpl.SakilaManagerImpl">
<property name="SakilaDao" ref="dao"></property>
</bean>
</beans>
SakilaAction.java
package com.java.Training.action;
import java.util.ArrayList;
import java.util.HashMap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.google.gson.Gson;
import com.java.Training.manager.SakilaManager;
import com.java.Training.managerImpl.SakilaManagerImpl;
import com.java.Training.model.SakilaPojo;
public class SakilaAction {
// PARAMETERS
private String start;
private String limit;
private String sort;
private String filter;
// RETURN VALUE
private String result;
// SakilaManager manager= new SakilaManagerImpl();
private HashMap <String, Object> dataMap= new HashMap <String, Object>();
public String getData() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SakilaManager manager = (SakilaManager) context.getBean("manager");
try {
ArrayList <SakilaPojo> jArray= (ArrayList<SakilaPojo>) manager.getData(Integer.parseInt(start), Integer.parseInt(limit), filter, sort);
Integer count= manager.getCount(Integer.parseInt(start), Integer.parseInt(limit), filter);
dataMap.put("Data", jArray);
dataMap.put("Total", count);
}
catch(Exception e) {
e.printStackTrace();
}
Gson gson = new Gson();
setResult(gson.toJson(dataMap));
return "success";
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getLimit() {
return limit;
}
public void setLimit(String limit) {
this.limit = limit;
}
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
SakilaManagerImpl.java
package com.java.Training.managerImpl;
import java.util.List;
import com.java.Training.Dao.SakilaDao;
import com.java.Training.DaoImpl.SakilaDaoImpl;
import com.java.Training.manager.SakilaManager;
import com.java.Training.model.SakilaPojo;
public class SakilaManagerImpl implements SakilaManager{
SakilaDaoImpl dao;
// = new SakilaDaoImpl();
public List<SakilaPojo> getData(Integer start, Integer limit, String filter, String sort) {
return dao.getData(start, limit, filter, sort);
}
public int getCount(Integer start, Integer limit, String filter) {
return dao.getCount(start, limit, filter);
}
public SakilaDaoImpl getDao() {
return dao;
}
public void setDao(SakilaDaoImpl dao) {
this.dao = dao;
}
}
SakilaManager.java
package com.java.Training.manager;
import java.util.List;
import com.java.Training.model.SakilaPojo;
public interface SakilaManager {
public List<SakilaPojo> getData(Integer start, Integer limit, String filter, String sort);
public int getCount(Integer start, Integer limit, String filter);
}
In SakilaManagerImpl.java I've tried using SakilaDao dao; in place of SakilaDaoImpl dao; which is the Interface of SakilaDaoImpl class. But same it's throwing the same error.
the property name in the xml must match the field name in SakilaManagerImpl
<bean id="manager" class="com.java.Training.managerImpl.SakilaManagerImpl">
<property name="dao" ref="dao"></property>
</bean>

How to implement generic service-layer class in Spring Framework?

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);
}
}

Injected Beans are null in abstract class

I have abstract user service where I autowired two beans: Repository and AbstractMapper, but when I run test for that class, all faild with NullPointerException. When I run, for example, save test for that service in dubug, it show me that both beans are null. Anybody had this problem? This is my code:
AbstractService
package com.example.shop.service;
import com.example.shop.dto.AbstractMapper;
import com.example.shop.entity.Identifable;
import com.example.shop.repository.IRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
#Service`enter code here`
public abstract class AbstractService<E extends Identifable, D> implements IService<E, D> {
private IRepository<E> repository;
private AbstractMapper<E, D> abstractMapper;
#Autowired
public AbstractService(IRepository<E> repository, AbstractMapper<E, D> abstractMapper) {
this.repository = repository;
this.abstractMapper = abstractMapper;
}
#Override
public D get(Long id) {
E e = repository.get(id);
return abstractMapper.entityToDto(e);
}
#Override
public List<D> getAll() {
List<E> all = repository.getAll();
List<D> allDtos = all.stream()
.map(e -> abstractMapper.entityToDto(e))
.collect(Collectors.toList());
return allDtos;
}
#Override
public E save(D d) {
E e = abstractMapper.dtoToEntity(d);
return repository.save(e);
}
#Override
public E update(D d) {
E e = abstractMapper.dtoToEntity(d);
return repository.update(e);
}
#Override
public E delete(D d) {
E e = abstractMapper.dtoToEntity(d);
return repository.delete(e);
}
#Override
public void deleteAll() {
repository.deleteAll();
}
}
UserServiceImpl
package com.example.shop.service;
import com.example.shop.dto.UserDto;
import com.example.shop.dto.UserMapper;
import com.example.shop.entity.User;
import com.example.shop.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class UserServiceImpl extends AbstractService<User, UserDto> implements UserService {
private UserRepository repository;
private UserMapper userMapper;
#Autowired
public UserServiceImpl(UserRepository repository, UserMapper userMapper) {
super(repository, userMapper);
}
}
Abstract Mapper
package com.example.shop.dto;
import org.springframework.stereotype.Component;
#Component
public interface AbstractMapper<E, D> {
E dtoToEntity(D d);
D entityToDto(E e);
}
User Mapper:
package com.example.shop.dto;
import com.example.shop.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class UserMapper implements AbstractMapper<User, UserDto> {
private AccountMapper accountMapper;
#Autowired
public UserMapper(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
#Override
public User dtoToEntity(UserDto dto) {
if (dto == null) {
return null;
}
User user = new User();
user.setId(dto.getId());
user.setEmail(dto.getEmail());
user.setPassword(dto.getPassword());
user.setLogin(dto.getLogin());
user.setAccount(accountMapper.dtoToEntity(dto.getAccountDto()));
return user;
}
#Override
public UserDto entityToDto(User user) {
if (user == null) {
return null;
}
UserDto dto = new UserDto();
dto.setEmail(user.getEmail());
dto.setLogin(user.getLogin());
dto.setPassword(user.getPassword());
dto.setId(user.getId());
dto.setAccountDto(accountMapper.entityToDto(user.getAccount()));
return dto;
}
}
Class with #SpringBootApplication
package com.example.shop;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ShopApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(ShopApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("Test");
}
}
And my tests for Service:
package com.example.shop.service;
import com.example.shop.dto.UserDto;
import com.example.shop.entity.User;
import com.example.shop.repository.IRepository;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.mockito.Mockito.*;
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserServiceImplTest {
private static final Long VALID_ID = 1L;
#Mock
private IRepository<User> repository;
#InjectMocks
private UserServiceImpl service;
#After
public void tearDown() {
repository.deleteAll();
}
#Test
public void get() {
service.get(VALID_ID);
verify(repository, times(1)).get(anyLong());
}
#Test
public void save() {
UserDto dto = createUser();
service.save(dto);
verify(repository, times(1)).save(any());
}
#Test
public void getAll() {
service.getAll();
verify(repository, times(1)).getAll();
}
#Test
public void update() {
UserDto dto = createUser();
service.update(dto);
verify(repository, times(1)).update(any());
}
#Test
public void delete() {
UserDto dto = createUser();
service.delete(dto);
verify(repository, times(1)).delete(any());
}
#Test
public void deleteAll() {
service.deleteAll();
verify(repository, times(1)).deleteAll();
}
private UserDto createUser() {
return new UserDto();
}
}
There are several problems with this code. First of all you do not need to annotate the abstract classes with service or component. Abstract classes cannot be instantiated, therefore there is no bean.
Second: autowire of classes having generics wont work. As soon as you have several bean, it wont be unique anymore.
Checkout if your classes get instantiated. Maybe you need to add #componentscan.
Your test is located under: com.example.shop.service and therefore it only scans the beans under this package. You should either move your test or add the beans by using the componentscan annotation

How to implement a method in a DAO?

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).

GenericDao, Class<T> is null

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);
}
}

Categories