Generic DAO disadvantages? - java

I want to create a DAO layer for my application. After some googling I found that many peoples uses Generic DAO approach (Don't repeat the DAO!).
But I did not like this approach.
What if I need slightly different interfaces between DAO for different DAO implementations? (i.e. methods in generic interface not exactly same which I want to create in my DAO implementations)
What if my entity's primary key consists of more than one attribute?

If you need a slightly different DAO for a particular entity, you can always extend a generic one(MySpecificDAO <....> extends GenericDAO<....>). Primary key can be composite itself, but it's impossible to have 2 primary keys .

Straight from the article you linked to:
Extending GenericDAO
The interface for each DAO is, of course, based on the GenericDao interface. I just need to adapt the interface to a specific domain class and extend it to include my finder methods. In Listing 6, you can see an example of the GenericDao interface extended for a specific purpose
Regarding your last question: by definition, an entity has one and only one primary key.

Disadvantage: you still have to implement the DAO. Stop following advice from 6 years ago, and use Spring Data repositories instead. Then you don't have to write any implementations at all.

What if I need slightly different interfaces between DAO for different
DAO implementations?
you can override the method in your GenericDaoImpl class. or create a new method.
What if my entity have 2 or more primary keys?
I guess you meant compound-key scenario. Note that usually the findOne/readOne/getOne method in GenericDao would expect a parameter, (T key) the T here is type, it could be composite primary key.
for example:
class PersonPK{
private String name;
private Date birthday;
.....
}

You can find here a Generic DAO a working and improved implementation of that very article. Just checkout the Example.java at the bottom of the page. In this example you can see how you can define "slightly different interfaces between DAO for different DAO
implementations".

Related

Multiple Inheritance in Java - Spring Data

I want to create a DAO class named BaseDAO that should have the JPA and JDBC capabilities in Spring. I mean, I want to extend JPADAOSupport and JDBCDAOSupport classes of spring in to my BaseDAO class. I am aware that multiple inheritance is not an option in Java.
I have created two separate Base classes like BaseJPADao and BaseJdbcDao extending the respective classes. Is it possible to have a single class to extend both? Is there any design pattern solving this issue. Please advise.
Why don't you have a DaoGateway bean having injected the actual JPA DAO and the JDBC DAO beans.
This gateway can then decide which DAO to delegate a given request (to JPA or to JDBC).
You should always favour composition vs inheritance when reusing functionalities.
no it is not. if it was possible, you would still have the same result as in
one class extending JPADAOSupport and JDBCDAOSupport, which you yourself say you know is not possible because multiple inheritance is impossible.
you can write to an interface, and provide two implementations, though.
This would be easy to do with delegation if they both had interface level access you want:
public class MyUberClass implements WhateverJPADAOSupportDoes, WhateverJDBCDAOSupportDoes {
private JPADAOSuport jpa;
private JDBCDAOSupport jdbc;
// now implement all methods specified by the interfaces on the class signature and delegate to their respective member
}
But it seems you want access to all of their public methods. As there is no interface for both you can do the same as above but it can't be of both types simultaneously. The language expressly denies you this.
Your only other option is to create an adapter interface that your code can rely on and then use the combination delegation. If you're hoping to have one class that you can just drop in as a substitution for both then the answer is you can't.

What's the difference between a Home object and a DAO?

In a Wicket/Spring/Hibernate project I inherited I find the following pattern:
For each Entity there exists an abstract class called EntityHome generated by Hibernate Tools which provides methods for finding, persisting, merging, and removing Entity. In another package there are classes called EntityDao for each EntityHome which in most cases simply extend EntityHome without adding any additional functionality.
Normally I would create a single generic DAO for handling persist, find, merge, and remove generically and have all DAOs extend this one.
The closest thing to some kind of documentation for Home Objects I found is http://docs.jboss.org/seam/1.1GA/reference/en/html/framework.html#d0e6756 and what I read there pretty much matches what a DAO should do.
So my question is: what is the difference between a Home Object and a DAO? Is there any at all?

How to define polymorphism in JPA

there is a situation. For example, I am designing simple blog. There are articles and photographies. Users can add their comment to both of them. So when I write it in Java, it looks like this:
public interface Commentable { ... }
public class Article implements Commentable { ... }
public class Photo implements Commentable { ... }
public class Comment {
...
private Commentable commentTo;
}
This is clear and I hope that design is correct. But now I would like to persist it in database and I want to use JPA annotations. Primarily I have to use JPA 1.0 but if there is not solution I would like to know how to do it in JPA 2.0. I found out that there is a way with classic inheritance but I think that Commentable shouldn't be a parent of these object, it is only extension in light of design.
Is there any way how to persist it without changing of desing, please? Thanks a lot
Is there any way how to persist it without changing of design, please? Thanks a lot
JPA doesn't really support your design (to be precise, you can map a relation pointing to an interface if there is a single implementation, but that's not your case). Your JPA provider might have some support for this though (e.g. EclipseLink has a #VariableOneToOne annotation).
With standard JPA, the usual approach would be to use an abstract class (with or without your interface) and to use inheritance. For example (keeping the interface):
public class Comment {
...
#OneToOne(targetEntity=MyAbstractBaseClass.class)
private Commentable commentTo;
}
Where both Article and Photo would extend MyAbstractBaseClass and implment the interface.
The JPA wikibook has two good sections on this topic, see below.
Resources
JPA Wikibook:
My relationship target is an interface
Variable and Heterogeneous Relationships

Best way to share Java implementation between concrete JPA classes?

I have about 10 different entities in my J2EE application that right now share the exact same implementation. They all inherit from the same generic abstract class that has been annotated as a #MappedSuperclass, but this class contains none of the implementation I have repeated in all the concrete subclasses.
If I could, I'd put all the various fields and collections on this abstract superclass and therefore put the implementation methods there too -- all in one place instead of 10. However, due to JPA restrictions I cannot add JPA annotations to generic fields or accessors.
While I normally favor delegation to implementation inheritance anyway, due to another JPA restriction that says you can't have an embedded entity with a collection the idea of using a delegate also won't work.
When I had only 3-4 of these entities and 2-3 methods, it wasn't a big deal, but now I have about 10 -- and about 7-8 methods each...and some of the methods are getting really complex. And the "cut-copy-paste" inheritance I am using really sucks.
Any other brilliant ideas out there?
Double-check whether these "restrictions" actually hold true for your JPA provider. I've had embedded objects with collections and it has been fine (with Hibernate). And I've had a #MappedSuperclass with mapped fields.
You can try omitting the #MappedSuperclass, and make the superclass abstract and an #Entity with the proper inheritance hierarchy.
It turns out you can use either implementation inheritance or delegation as long as you are sure to use property access mode for your JPA annotations. I was using field access mode for JPA annotations and that was causing me no end of suffering because I could not annotate a generic field type.
However with property access mode I simply create my generic abstract implementation without annotating it as an entity, mappedsuperclass, embeddable, or anything. This way JPA will ignore it. Then, in the concrete subclasses, I create protected getter and setters methods as needed and put the JPA annotation on those.
Turned out to be deceptively simple.

Best way to add annotations to inherited methods

I have a number of abstract superclasses from which my concrete class inherit various methods. Some of these methods need to have JPA or JAXB annotations placed on them in the concrete class. Currently I do this via the following:
#MyLocalAnnotations
#Override
public method inheritedMethodHere (yadda yadda)
{
super.inheritedMethodHere(yadda yadda);
}
Is there a way to do this without overriding the method? It seems like such a waste to override a method only to supply local annotations.
Unfortunately, there isn't a better way than what you are doing now. To do what you are describing you will have to override the method, considering that your JPA annotation will need information specific to the concrete class.
With JPA annotations, you actually have two options -- you can annotate the methods, or you can annotate the properties. On our project we've standardized on annotating properties rather than methods, but this won't help you either, as the properties are presumably part of the concrete class. (If they are somehow shared in the super-class, then you REALLY will need to annotate the methods, and override them).
Its hard to make a recommendation without seeing your schema, but if your entity classes have so much in common that they share many properties in the super-class -- might they simply be stored in the same table, perhaps with a differentiating type column?
Or alternatively if they are not nearly identical, might you just reproduce the common properties in each concrete class? You might be causing yourself more work rather than saving yourself by trying to capture the common properties in the super class. Since you will have to annotate them individually in the concrete classes, just declare them in the concrete classes. If you need common methods that interact with these properties, a separate Utility class to capture those functions could be the answer.
On our project we DO sometimes use a common super class for entities, but it captures some meta-data about the entity -- nothing that would impact persistence logic. Therefore, no JPA annotations are needed (nor would they make sense) in the abstract class.

Categories