Dao Registry refactoring - java

Using the generic dao pattern, I define the generic interface:
public interface GenericDao<T extends DataObject, ID extends Serializable> {
T save(T t);
void delete(ID id);
T findById(ID id);
Class<T> getPersistentClass();
}
I then implemented an default GenericDaoImpl implementation to perform these functions with the following constructor:
public GenericDaoImpl(Class<T> clazz) {
this.persistentClass = clazz;
DaoRegistry.getInstance().register(clazz, this);
}
The point of the DaoRegistry is to look up a Dao by the class associating to it. This allows me to extend GenericDaoImpl and overwrite methods for objects that requires special handling:
DaoRegistry.getInstance().getDao(someClass.getClass()).save(someClass);
While it works, there are a few things that I don't like about it:
DaoRegistry is an singleton
The logic of calling save is complicated
Is there a better way to do this?
Edit
I am not looking to debate whether Singleton is an anti-pattern or not.

First of all, what is your problem with DaoRegistry being singleton?
Anyway, you could have an abstract base class for your entities that'd implement save like this
public T save(){
DaoRegistry.getInstance().getDao(this.getClass()).save(this);
}
then you could simply call someEntity.save()
Or it may be more straightforward if the entity classes itself implemented the whole GenericDao interface (save, delete and find methods), so the contents of your GenericDaoImpl would be in the base class of your entities.

It could be better to use instance of DaoRegistry instead of static methods. It would make it more manageable for test configurations. You could implement it as
#Component("daoRegistry")
public class DaoRegistry {
#Autowired
private List<GenericDao> customDaos;
private GenericDao defaultDao = new GenericDaoImpl();
public <T> T getDao(Class<T> clazz) {
// search customDaos for matching clazz, return default dao otherwise
}
}
Also you could add save method to it and rename accordingly. All customised daos should be available as beans.

Related

Is it better to use aggregation over inheritance when creating a generic CRUD component?

I have a question. I have these classes:
public interface CRUDService<MODEL extends BaseModel<ID>,ID extends Serializable>
{
List<MODEL> findAll();
MODEL findById(ID id);
// + delete, save & update methods
}
public abstract class AbstractCRUDService<MODEL extends BaseModel<ID>,ID extends Serializable> implements CRUDService<MODEL,ID>
{
//overriding the CRUDService interface methods here.
}
Is it better to extend each service from AbstractCRUDService like this:
public class DefaultProductService extends AbstractCRUDService<ProductModel,Long> implements ProductService
{ //some methods here}
or should I remove abstract from AbstractCRUDService and inject this service in the DefaultProductService ?
public class DefaultProductService implements ProductService {
#Autowired
private CRUDService<ProductModel,Long> crudService;
// override "ProductService" methods here.
}
It depends on your requirement.
If all Model Types, need the same CRUD implementation, you can go with your 2nd approach: composition.
However, if different Model objects require different CRUD implementations, the inheritance would fit better. For example, for all ProductModels Del(obj) will remove the object from the DB table, however, for all OrderModels Del(obj) doesn't remove the data, instead, it does something else, throw an exception, for example.
Yes, it is. You need to prefer composition over inheritance
here a really good post to read about it
composition over inheritance

Can i use generic method to acess data from different entities in hibernate

For example: i have User.class and Post.Class
I want to get all rows from this tables with hibernate.
It is done with
TypedQuery<Post> query = SessionFactory.getCurrentSession().createQuery("from Post");
Also i have dao layer, UserDao and PostDao. and i have abstract class CrudDao with methods like:
public abstract class CrudDao<T> {
#Transactional
public void save(T entity) {
SessionFactory.getCurrentSession().save(entity);
}
}
So my user and post dao just extend this crudDao and i don't need to write save method for them. When i want to get all rows i need to write "from MyEntitie". But i want to make this method also abstract, so i don't need to write it multiple times for each dao. But i can't write "from T" in abstract method.
I also tried to do like this:
List<T> getAll(Class<T> type){
CriteriaQuery<T> criteria = builder.createQuery(type);
criteria.from(type);
return
SessionFactory.getCurrentSession().createQuery(criteria).getResultList();
}
So in my service i call my dao like this:
PostDao.getAll(Post.class);
And i was told that my service shouldn't know about my entity and my dao call in service should be
PostDao.getAll();
And if i do like this ^ i need to write getAll method in every dao and it looks like a lot of copypasted code.
Can yoy give me some advice on how to do it or how you do it in your projects?
What i learned from deHaar reply:
You can create abstract methods with generic dao and call generic class if you create a variable of this generic type/ For example my generic dao:
public abstract class CrudDao<T> {
private Class<T> type;
public CrudDao(Class<T> type){
this.type = type;
}
#Transactional
public T getById(,int postId) {
return sessionFactory.getCurrentSession().get(type, postId);
}
}
So you need only to write a constructor that calls superclass constructor in your child Dao's that extend generic dao.
Like :
public class PostCommentDao extends CrudDao<PostComment> {
public PostCommentDao(){
super(PostComment.class);
}
}
And now everything works from generic dao!
As Tanos said: small price to pay for salvation.
In my opinion, generic DAO is an antipattern. Spring provides you with excellent three-tier architecture made of #Controller (for mvc and rest), #Service (for functionality reusability) and #Repository (for data access). It's okay to have a little bit more code just to leave it with a single responsibility.

How to override Spring Data JPA repository base methods?

I have some entity type that needs additional logic on saving (to be precise, I want to save position at the moment of saving). I don't want to do it with any DB-specific features, like triggers, because I'm not sure what will be the data storage used in future.
So I would like to override save() method.
In Spring Data JPA documentation I can see two ways of providing own implementation for repository classes:
Extend base repository class and tell Spring Data to use it.
Defining an interface (in my case I assume PositionedRepository) with an implementation class (PositionedRepositoryImpl).
Problem with first way - I don't want to implement it for all repositories, only two entity types are positioned.
Problem with second way - I don't have access to base repository methods, so apart from position calculation I would need to somehow build all of the queries, normally provided by base repository.
Any way to extend base repository class just for specific repository types?
Don't do that logic in the repository itself. Think about repositories as a dumb layer between java and the database. It just passes data from end to the other.
Instead you should handle that case in a different layer. A more intelligent one. The business logic layer.
See this example:
#Service
public class MyEntityService{
private final MyEntityRepository myEntityRepository;
private final OtherEntityRepository otherEntityRepository;
#Autowired
public MyEntityService(MyEntityRepository myEntityRepository,
OtherEntityRepository otherEntityRepository){
this.myEntityRepository = myEntityRepository;
this.otherEntityRepository = otherEntityRepository;
}
public void save(MyEntity myEntity){
// do stuff with otherEntityRepository
myEntitiyRepository.save(myEntity);
}
}
you can :
public class CustomJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
private final JpaEntityInformation<T, ?> entityInformationWrap;
private final EntityManager emWrap;
public CustomJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
entityInformationWrap=entityInformation;
emWrap=entityManager;
}
#Override
public <S extends T> S save(S entity) {
//doing
}
}
then main class add:
#EnableJpaRepositories(repositoryBaseClass = CustomJpaRepository.class)
As third option you can extend SimpleJpaRepository that implements JpaRepository and JpaSpecificationExecutor.
In this way, you could benefit from the default implementation of JpaRepository while being the ability to override these methods.
For example :
#Repository
public class PositionedRepository extends SimpleJpaRepository<Positioned, Long> {
#Override
public Positioned save(Positioned positioned) {
...
}
}
As fourth option you can also define your own savePositioned() method that uses under the hood the JpaRepository.save().

Creating and initializing class with default values

While working on an web-application , I need to get a set of classes at few steps and I am thinking to separate this logic to a simple Factory so as based on the Class type We can create class instance as well init it with default values.
Current structure of Class hierarchy is
public interface DataPopulator<Source,Target>{
// some method decaration
}
Abstract class
public abstract class AbstractDataPopulator<Source,Target> implements DataPopulator<Source, Target>{
// some common implimentation
}
And now classes which will be used as actual implementations like
Type1Populator extends AbstractDataPopulator.
Type2Populator extends AbstractDataPopulator.
Each of these implementation needs a set of common dependencies based on what functionality is being executed by those Populators.
As of Now I am creating instance with new and than filling those dependencies with simple setter methods.
I am thinking about creating a simple factory pattern like
public interface PopulatorFactory{
<T extends Object> T create(String className) throws Exception;
<T extends Object> T create(Class populatorClass) throws Exception;
}
Abstract class
public abstract class DefaultPopulatorFactory impliments PopulatorFactory{
public <T> T create(final Class populatorClass) throws Exception{
return Class.forName(populatorClass);
}
// other method.
}
Implementation classes
public Type1PopulatorFactory extends DefaultPopulatorFactory {
public <T> T create(final Class populatorClass) throws Exception{
final T populator= super.create(populatorClass);
}
}
I also want to initialize newly created instances with some default values specific to each implementation, but I'm not sure what's the best way to do this?
Should I define another method say initDefaults?
What is the best way to pass those dependencies to these poulators.
Is the approach outlined by me fine or is it overly complicated?
In cases when you are building not-so-trivial objects it is usually better to use the Builder pattern instead of a Factory.
In your case if you don't need external data sources you can simply write constructors for your classes where you can supply the default values and get rid of the contraption in your question.
If you use the Builder pattern you can simplify your framework by using a Builder object for the common data and a SomeOtherBuilder which extends from Builder and adds the custom values of the specialized implementation. You can make your classes constructors which are taking a Builder object.
public class Builder {
// your fields go here
}
public class SomeOtherBuilder extends Builder {
// your specialized fields go here
}
public class YourClass {
public YourClass(Builder builder) {
// construct it here
}
}
You can also make your classes generic with using something like T extends Builder.

Hibernate using DetachedCriteria with interfaces

Using Hibernate 3.6.8.Final and Spring 3.0.5.RELEASE , I'm trying to add some Common DAO functionality for classes that have multiple implementations overridden higher up to implement the specific classes however it doesn't work for DetachedCriteria.
Example:
In base class:
public interface ICat {
public void setMeowSound(String meow);
public String getMeowSound();
}
Then each inherited project would define the hibernate annotations.
e.g.
#Entity
#Table(name="SQUAWKY_CATS")
public class SquawkyMeowingCat implements ICat, Serializable {
#Id
#Column(name="SQUAWK_NAME")
private String meow;
public String getMeowSound() {
return meow;
}
public void setMeowString(String meow) {
this.meow = meow;
}
}
This means I can use:
Criteria criteria = Session.createCriteria(ICat.class);
And Spring/Hibernate knows that it pulls the annotations for ICat from the concrete inheritance in the particular project.
However if I try to do:
DetachedCriteria subQuery = DetachedCriteria.forClass(ICat.class,"inner"); // etcetera
then I get an Unknown entity at runtime for ICat.
Now this makes sense as in the first instance is creating it off the Session so it has all the configuration that it needs whereas the DetachedCriteria is a static method however it errors when trying to do the
criteria.list()
by which time it has picked up the Session and should know that ICat is actually a SquawkyMeowingCat which has all the annotations.
So my questions are two part:
1) Is this known behaviour and will be like this forever more?
2) Can anyone think of a simple way around it without using an Interface and concrete ClassHolder which hands back the instance of the class it needs to create?
I'm not sure about the case of the DetachedCriteria, but one way to avoid explicit dependence on the concrete class might be to query Hibernate's metadata using the interface:
public <T> Class<? extends T> findEntityClassForEntityInterface(
SessionFactory sessionFactory,
Class<T> entityInterface
) {
for (ClassMetadata metadata : sessionFactory.getAllClassMetadata().values()) {
Class entityClass = metadata.getMappedClass(EntityMode.POJO);
if (entityInterface.isAssignableFrom(entityClass)) {
return entityClass;
}
}
return null;
}
With the usual caveats about the robustness of illustrative code spippets.

Categories

Resources