I have configured a custom generic service DAO for my spring / hibernate project - the idea being that I can reuse it easily from my controllers.
It essentially looks like this:
public class DefaultService<T> {
private Class<T> e;
public String className(Class<T> e) {
String clip = e.getName();
clip = clip.substring(clip.lastIndexOf('.') + 1, clip.length());
return clip;
}
public List<T> getAll(Integer status) {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("FROM " + className(e) + " WHERE status = " + status);
return query.list();
}
...
Which gets referenced by:
@Autowired
public DefaultService<Address> addressService;
addressService.get(1);
However the String clip = e.getName()
line throws a Null pointer exception. I can get this to work if I move the class into the attributes section (so addressService.get(Address.class, 1)
but I find this somewhat untidy, especially when there are multiple different classes being called upon.
Is there some way to get the class to generate a value correctly without repeatedly adding it into all my functions?
Thanks in advance.
I did something similar, you need the generic class to be a constructor argument as well, mine uses hibernate entities, but you could pass in the string of table name.
You can then subclass (if you need to) to customize or simply set up you bean in the spring config like below t :
So in your code you could then reference tagRepository like so (no other cod eis needed than that posted above, and below) :
Also, I would call it a repository not a service, a service deals with different types and their interactions (not just one). And for specifically your example using SQL strings :
and have your beans defined like so
And then you can alsow create subclasses youself where necessary :
As I understand you got NPE because you did not set any value for this field. So you can resolve this problem by 2 ways:
protected Class getEntityClass() { return GenericTypeResolver.resolveTypeArguments(getClass(), DefaultService.class)[0]; }
or some workaround here
It's better to define a specific class for Address service
where
is an abstract method declared in DefaultService, and used (like your method className()) in your data access logic.
Using this approach, you will be able to add specific data access logic (example, getUsersByAddress)