Using identifiers and values from other places in a Spring CrudRepository - java

I'm learning how to extend Spring's CrudRepository interface to create a repository for an entity. But I'm having trouble implementing more complicated queries that use values that aren't hard-coded. Here's a contrived example. The HQL is not valid, but it shows what I'm trying to do:
import mypackage.DogTypeEnum;
public interface myRepository extends CrudRepository<Dog, Integer> {
int oldAge = 10; // years - old for a dog
#Query(SELECT dog From Dog dog WHERE dog.age > oldAge and dog.type = DogTypeEnum.poodle
public List<Dog> findOldPoodles()
}
So in the above example, I'm trying to query for all dogs of type poodle that are over a certain age threshold. I don't want to hard code either poodle or the value 10 because these values that will be used elsewhere in the code as well and I want to avoid duplication. I don't want to require the user to pass those values in as parameters either.
Is there a way to do this?

You could create a Interface that extend your repository as like this:
//Only complex querys
public interface MyRepositoryCustom {
List<Dog> findOldPoodles()
}
// Your Repository must extends to MyRepositoryCustom
public interface MyRepository extends CrudRepository<Dog, Integer>, MyRepositoryCustom {
// Declare query methods
}
//More complex query
public class MyRepositoryImpl implements MyRepositoryCustom {
#PersistenceContext
private EntityManager em;
public List<Dog> findOldPoodles() {
Query query = em.createQuery("SELECT dog From Dog dog WHERE dog.age > :oldAge and dog.type = :type");
query.setParameter("oldAge",10);
query.setParameter("type",DogTypeEnum.poodle.name);
return query.getResultList();
}
}
Remember all java class starts with a Upper Case letter.
This link can help you: Spring repositories

In my case I'll never have this problem, if you structure your project as the next package architecture shows, you won't have this problem:
View (Angular, JSP, JSF...) -- APP
Controller -- APP
Services -- Main Core
DAO -- Main Core
Entities -- Main Core
This way you make more modular, escalable, maintainable and comprehensive application.
It doesn't matter what technology you use in your view, you just have to invoque the correct method on the service.
In here, on the services package you could have a service for example:
#Service
public class ServiceDog extends Serializable {
#Autowired
private MyRepository myRepository;
int oldAge = 10;
public List<Dog> findOldPoodles() throws ServicioException {
return myRepository.findAllByAgeGreaterThanAndType(oldAge, DogTypeEnum.poodle);
}
}
Now you could use all the advantage you get from using spring-data-jpa reference or make a more simple JPQL Query.
This is a simple example but this way you make sure that each DAO speak with only one entity (It will only have the methods needed for this entity like save, delete.. with no dependencies with other DAOs), and the service are the ones on calling the different DAOs and make the necessary actions on them.
Hope this helps.

Related

Dynamically Identify entity class and JPA Interface

I have a requirement that based on profile I need to inject 2 different classes into DAO layer to perform CRUD operation. Let's say we have class A and Class B for profiles a and b respectively. Now in the DAO layer without using if else condition (As I am using that currently based on the profile, I am using service layer to call 2 different methods 1.saveA(), 2.saveB().) But is there any way to make it more generic and based on profile or either by the class reference I can instantiate different entity as well as JPA Classes? I tried to use
<T extends Parent> T factoryMethod(Class<T> clazz) throws Exception {
return (T) clazz.newInstance();
}
but this also will force me to cast the returned object to a class. I tried creating a parent P for both class A and B. and used them instead but got confused when injecting the entity types to JPARepository.
I tried creating a SimpleJPARepository but didnt worked as there are overridden methods in ARepository and BRepository.
Or,
is there a way I can use the same entity class for 2 different tables? that way it can be solved. for 1 profile I have different sets of columns whereas for 2nd profile I have different columns.
this is how I am expecting: Would it be possible? or, how I am doing now is correct?
public void doStuff(Class<T> class){
GenericRepository repo;
if(class instanceof A){
//use ARepository;
repo = applicationContext.getBean(ARepository);
}else{
//use BRepository;
repo = applicationContext.getBean(BRepository);
}
repo.save(class);
repo.flush();
}
You can create a method utility like following: The key is the class type of the entity and the value is the repository.
Map<Class<? extends Parent>, JpaRepository> repoMapping = new HashMap<>();
#PostConstruct
public void init(){
repoMapping.put(A.class, applicationContext.getBean(ARepository));
repoMapping.put(B.class, applicationContext.getBean(BRepository));
}
public JpaRepository getRepo(Class<? extends Parent> classs){
return repoMapping.get(classs);
}

Spring Boot: How to avoid too many JPA repositories for each domain class

I'm building a Spring Boot application containing more than 10 domain classes which need to be persisted in a SQL database.
The problem is that I need to create an interface for every single domain class, so something like this for each one:
public interface BehandelaarRepo extends CrudRepository<BehandelCentrum, Long> {
}
Is there any way to decrease the number of repositories by using some kind of design pattern or whatever? Any suggestions?
You can actually make it some easier for yourself by using generics the same way Spring Data JPA does it:
public interface JpaRepository<T extends Serializable, ID extends Serializable> {
public <S extends T> S save(S object);
}
The trick is that you can use all subclasses, and you're getting that class back as well. I always create one superclass, so I get rid of my ID generic:
#MappedSuperclass
public class JpaObject {
#Id
#GeneratedValue
private Long id;
(.... created, last updated, general stuff here....)
}
I create my #Entity classes as a subclass from this JpaObject.
Second step: create my super interface for future usage of special queries:
#NoRepositoryBean
public interface Dao<T extends JpaObject> extends JpaRepository<T, Long> {
}
Next step: the generic Dao which looks some stupid and remains empty at all times
#Repository
public interface GenericDao extends Dao<JpaObject> {
}
Now have a sharp look at that save method in CrudRepository / JpaRepository:
public <S extends T> S save(S object);
Any object extending JpaObject (S extends JpaObject) now can be given as a parameter to all methods, and the returntype is the same class as your parameter.
(Aziz, als het handiger is, kan het ook in het Nederlands uitgelegd worden :P Groet uit Zwolle)
Well, I had a similar problem. I resolved it by creating new layer, namely
RepositoryManager (or ModelService) singleton that had all the repo interfaces and methods that used them.
If you want you can implement generic save method (then call that class ModelService) that resolves model types through reflection and chooses the corresponding repository.
It was also handy for decoupling cache implementation (I used spring cache).

Spring CommandLineRunner Interface Implementation

So I was following the tutorial here: https://spring.io/guides/gs/accessing-data-jpa/
and it works fine, I'm trying to implement it in my application (Because it makes JPA so easy to use), but I'm confused.
Where it has
#Bean
public CommandLineRunner demo(CustomerRepository repository)
and then it acts on the repository
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
How can it act on an interface? CustomerRepository is an interface, and I can't instantiate it
CustomerRepository c = new CustomerRepository()
cant be done, and I don't have any classes that implement the interface. I just wanted to do something like
CustomerRepository c = new CustomerRepository()
c.save(new Customer("whatever", "whatever")
but I can only use it in the CommandLineRunner bean method. Why can I do this with commandlinerunner but cant do it with another class?
I was thinking I could just make a class that extends CustomerRepository, but then I read that the interface actually does all the method implementation itself (JPA does it) so you don't have to worry about it.
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
so if I extended it, wouldn't I have to override the findbylastname() method, meaning JPA wouldn't do it itself?
Thanks for any assistance.
so if I extended it, wouldn't I have to override the findbylastname()
method, meaning JPA wouldn't do it itself?
No, it is not JPA which does the job but Spring which generates by APO some JPA processings.
With Spring Repository, you have multiples ways of doing :
write your own SQL/JPQL query.
use naming convention in the method name to write the query
In both cases, you don't need to implement directly the interface you declare here :
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
Because as you understood, the job is performed for you by Spring.
For example, in the case you quote, you use naming convention in the method name to write the query.
When Spring inspects your interface and sees the method findByLastName(String lastName), it associates the method name to a query which does a find with a match by lastName field. So, it generate a JPQL query like that :
select c from Customer c where c.lastName=%lastName
and it sets the lastName param with the effective parameter used when the method is call.
I extended it, wouldn't I have to override the findbylastname()
method, meaning JPA wouldn't do it itself ?
No, you don't need to implement the methods as spring-data-jpa will take care of it, you can look here on how Spring data repository interfaces are actually implemented by proxy at runtime.
The main point that you need to remember is that spring data has got few rules to derive the sql queries from the method names (like findByLastName(), findByLastnameOrderByFirstnameAsc(), etc..), you can look here to understand how method names work and they are related to field names of your entity bean.
If you wanted to write some complex queries which can't be derived from method names you can use #Query for your methods.
If I made a class public class Cust implements CustomerRepository what
would I do when it asks me I have to implement the
findByLastName(String lastName); method that JPA is supposed to take
care of ?
If you wanted to implement repository to provide your custom behaviour for few of the methods for few of your methods, you can do that (like class Cust implements CustomerRepository), you can refer the section "Using JpaContext in custom implementations", it is well explained in the ref doc.

What is the improvement of using DAO in Java SE?

My project manager wants me to use DAO/DTO objects to access and retrieve data from database. Project is written in Java SE without using any framework or ORM. His arguments is to make code more testable and to improve code design. Does it make sense?
How about initializing DAO object? Should it be initialized when the instance of class having DAO field is created:
private PersonDao personDao = new PersonDaoImpl();
or rather initialized when it is necessary?
public class A {
private PersonDao person;
public List<Person> findAll() {
person = new PersonDaoImpl();
return person.getAll();
}
}
It allows to mock this interface easily, but is it right to the DAO pattern usage convention?
The Data Access Object is basically an object or an interface that provides access to an underlying database or any other persistence storage.
That definition from: http://en.wikipedia.org/wiki/Data_access_object
Maybe a simple example can help you understand the concept:
Let's say we have an entity to represent an employee:
public class Employee {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The employee entities will be persisted into a corresponding Employee table in a database. A simple DAO interface to handle the database operation required to manipulate an employee entity will be like:
interface EmployeeDAO {
List<Employee> findAll();
List<Employee> findById();
List<Employee> findByName();
boolean insertEmployee(Employee employee);
boolean updateEmployee(Employee employee);
boolean deleteEmployee(Employee employee);
}
Next we have to provide a concrete implementation for that interface to deal with SQL server, and another to deal with flat files, etc...
Hope that helps
To maximimze the benefits of testability and separation of concerns you should introduce the concept of Inversion of Control (IoC). When applying IoC to the management of object lifecycles the term Dependency Injection is used. What this means is that your class A should be completely agnostic of which implementation is instantiated when.
In order to achieve this you need an extra component to bootstrap your application and inject all classes with the correct implementations.
You could set up your dependency-receiving class like this (setter injection, you can also use constructors)
public class PersonServiceImpl implements PersonService {
private PersonDao personDao;
public List<Person> findAll() {
return personDao.getAll();
}
public setPersonDaoA(PersonDao personDao) {
this.personDao = personDao;
}
}
And a component to do the dependency injection:
public class ApplicationContext {
private PersonService personService;
private PersonDao personDao ;
public PersonService getPersonService() {
if (personService == null) {
personService= new PersonServiceImpl();
personService.setPersonDao(getPersonDao());
}
return personService;
}
public PersonDao getPersonDao() {
if (personDao == null) {
personDao = new PersonDaoIml();
}
return personDao ;
}
}
Then application startup would involve this:
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ApplicationContext();
PersonService personService = ctx.getPersonService();
personService.findAll();
}
}
As you can see, the ApplicationContext encapsulates knowlegde about:
which implementations to use
in which order to set a chain of dependencies
which dependencies are already instantiated or not
The PersonServiceImpl class is now completely testable and all concerns regarding object lifecycle management have been extracted from it.
In real life this if often done using a framework like Spring or CDI (which is becoming more and more popular recently). But in your situation, starting off with an approach like above might be a good first step. It will reap the immediate benefits mentioned by your project manager without incurring the overhead of introducing Spring, possibly changing your build too and having to learn how that works (e.g. with an XML context, source code context and/or annotations).
Introducing Spring at a later stage will be easy because all classes are already prepared for Dependency Injection. Just keep in mind that your factory (ApplicationContext in my example) should not take on any extra responsibilities like configuration management.
Also keep in mind that the above example of ApplicationContext is not a singleton. You yourself should make sure only one instance of it is created when your application starts, and all injections are handled by it. Creating duplicate instances could cause confusing bugs.
The DAO pattern is not an "enterprise" pattern. It's mostly seen in "enterprise" applications, but you can absolutely use in a an application written in SE only.
It's not because you're writing an SE application that you don't have to test, so indeed, your code will be more testable using the DAO pattern and IOC rather than using straight JDBC in your application.
The way you're implementing your class using the DAO is problematic because your class cannot be tested properly because of the tight coupling between your class A and your DAO implementation. You're better off using the IOC pattern as well with a framework like Guice or Dagger (both designed with SE in mind).
For a code example, look at slnowak's answer.
The way you are using it, it is still tightly coupled with your class A.
You should provide your DAO as a dependency, using constructor or setter. Probably the most preferable way is to use some kind of Inversion of Control (for example dependency injection framework).
Your class A should be something like:
public class A {
private PersonDao personDao;
// possibly an #Inject annotation
public A(PersonDao personDao) {
this.personDao = personDao;
}
public List<Person> findAll() {
return personDao.getAll();
}
}
And actually, I would consider it an antipattern this way. It depends on how you are about to use your class A.
If it contains different business logic - fine.
If it just dispatches a call to DAO (I don't like this name, maybe use Repository instead ;)) then it is just unnecessary layer of abstraction.
Another thing - you mentioned DTO. So a Person class is just a DTO in this case? Here we could have another antipattern. DTO is fine for example if you need to transform your business object(s) into something that is visible on the screen. Or to separate perstistence model from business model.
What I'm trying to say is: don't make a Person class just a data structure. Give it some behaviour.

DAO design pattern

So lets say we have a couple of entities we want to persist using DAO objects. So we implement the right interface so we end up with
class JdbcUserDao implements UserDao{
//...
}
class JdbcAddressDao implements AddressDao{
//...
}
So if I want to be able to switch persistance implementations from JDBC to JPA (for example) and vice versa, I'd need to have JPAUserDao and JPAAddressDao... Meaning if I had 20 entities, and decided to switch implementations(using DI container), I'd have to switch every Jdbc implementation with JPA in code.
Now it could be that I misunderstood how DAO works, but... If I just had
class JdbcDaoImpl implements UserDao,AddressDao{
//...
}
I'd then have all the JDBC implementations in one class, and switching implementations would be a piece of cake. Also, DaoImpl count is equal to number of Dao interfaces. Why not just group them by implementation (jdbc, JTA, JPA...) and have everything under one class?
Thanks in advance.
Having a single class implement every DAO interface in your entire application would be a rather bad design.
A more typical pattern is to have a BaseDAO interface (also often called GenericDAO) and have a JPABaseDAO, JDBCBaseDAO etc. These base classes will contain methods like find/get/read, save/store/persist, update/modify and delete/remove/purge.
Specific DAO interfaces like UserDAO then inherit from BaseDAO and concrete implementations like JPAUserDAO extends from JPABaseDAO.
A BaseDAO interface could look like this:
public interface BaseDAO <T> {
T getByID(Long ID);
T save(T type);
T update(T type);
void delete(T type);
}
And a UserDAO interface:
public interface UserDAO extends BaseDAO<User> {
List<User> getAllAuthorized();
}
Bare bones example of a JPABaseDAO implementing this interface:
#Stateless
public class JPABaseDAO<T> implements BaseDAO<T> {
#PersistenceContext
private EntityManager entityManager;
private final Class<T> entityType;
#SuppressWarnings("unchecked")
public JPABaseDAO() {
this.entityType = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
#Override
public T getByID(Long ID) {
return entityManager.find(entityType, ID);
}
#Override
public T save(T type) {
return entityManager.persist(type);
}
#Override
public T update(T type) {
return entityManager.merge(type);
}
#Override
public void delete(T type) {
entityManager.remove(entityManager.contains(type) ? type : entityManager.merge(type));
}
}
And some sample UserDAO implementation that would inherit from it:
#Stateless
public class JPAUserDAO extends JPABaseDAO<User> implements UserDAO {
#PersistenceContext
private EntityManager entityManager;
#Override
public List<User> getAllAuthorized() {
return entityManager.createNamedQuery("User.getAllAuthorized", User.class)
.getResultList();
}
}
In practice the base class can often do some other things transparently, for instance checking if an entity implements some kind of Auditable interface, and automatically setting the date and user that modified it, etc.
When using EJB to implement your DAOs, one strategy to change implementations would be to put all JDBC implementations in one package and all JPA implementations in the other. Then just include only one implementation package in your build.
The whole point of Dependency Injection is to make switching between implementation easier and to decouple the user from the provider. Hence all DI frameworks provide some way to "group" several implementations (here your JDBC-group and your JPA-group) and switch them in one place.
Also: Usually the number of consumers (in your case: some business logic working on users and addresses) is usually higher than the number of DAOs the DI framework will uncouple most of the stuff for you anyway. Assume: 50 business beans, two interfaces and two implementations for each interface (4 total): even basic DI will take care for the 50. Using grouping will halve that remaining rest for you.
There are definitely possibilities to implement the DAO pattern in a widely technology agnostic way such that switching persistence technology or even mixing multiple technologies becomes feasible. This article presents one implementation scheme including source code on github.
http://codeblock.engio.net/?p=180

Categories