I am working on a JavaEE project. All/Most classes i am working on reside on the data base. There fore all must support creating, editing and deleting a database entry.
I don't want to use any frameworks.I planed to execute the queries using the traditional prepared statements.
Currently I implemented it as follows
public interface Entity{
public boolean create(Entity e);//executes a query with the objects fields
public boolean change(Entity e);//executes a query to update fields of the entity
public boolean delete(Entity e);//deletes the entry
public ArrayList<Entity> getAll();//retrives all the entries in the database
}
Now my question
I'm i doing it right?
If a class inherites form a class that implements this interface how should it handel the methods? Should it override or call the super and add more code to handle more fields
Should i create another utility class to send the queries or is it ok if i add the database actions in the same class?
Appreciate in advance!
You are saying, that you are working on a Java EE project - so why don't use the APIs provided by it? There's a simple recommendation: Use JPA for it and only don't use prepared statements for CRUD operations of Java objects and don't reinvent an Entity which you already have at hand, together with an EntityManager doing all the operations you need on it.
What you are trying to implement is called a Data Access Object interface. It is in fact a well known and good practice, but judging from your interface name you want to use the CRUD methods directly whitin your entities and is not a good idea.
You should create an interface, say
public interface BookDAO{
public Book create(Book book);
public List<Book> read();
public Book update(Book book);
public Book delete(Book book);
}
with the CRUD methods. Then you can implement such interface depending on your database, say
class MySqlBookDAOImpl implements BookDAO{
private Connection conn;
private Connection getConnection(){
if(conn==null)
conn = mySqlConnectionPool.getConnection();
return conn;
};
#Override
public Book create(Book book){
Connection conn = getConnection();
String query = "INSERT... "
};
#Override
public List<Book> read(){
Connection conn = getConnection();
String query = "SELECT... "
};
#Override
public Book update(Book book){
Connection conn = getConnection();
String query = "UPDATE... "
};
#Override
public Book delete(Book book){
Connection conn = getConnection();
String query = "DELETE... "
};
}
and implement the abstract methods to communicate with the database using the correct database driver (depends also from your connection policies).
Regarding your other 2 questions:
When implementing a method from an interface you always ovveride it. You can't call a super method just because there is no super method. You call super only when you extend and override the method from the parent class.
The DAO should take care of sending the queries to the database and the DAO is going to create them within its methods.
Why are you so reluctant to use a framework or built in API? There are really good ones that can spare you a lot of work (like JPA).
You should distinguish entities and DAOs. Entities are the data, DAOs interact with the DB.
For example:
public interface Entity<K extends Serializable> {
K getId();
}
public interface Dao<K extends Serializable, E extends Entity<K>> {
E create(E entity);
E update(E entity);
E delete(E entity);
E get(K id);
List<E> getAll();
}
Then, implementations:
public class User implements Entity<Integer> {
private Integer id;
public User(Integer id) {
this.id = id;
}
#Override
public Integer getId() {
return id;
}
}
public class UserDao implements Dao<Integer, User> {
#Override
public User create(User entity) {
// build query
}
#Override
public User update(User entity) {
// build query
}
#Override
public User delete(User entity) {
// build query
}
#Override
public User get(Integer id) {
// build query
}
#Override
public List<User> getAll() {
// build query
}
}
This can be improved by having a BaseDao abstract class for example, since DAOs will have common code for sure.
Actually I can see you are missing a very basic operation wchich is acceessing objects:
public boolean read(Entity e);
You should also reconsider your class name to have a more relevant one (what this class is intended to do) since naming it as Entity gives the allure of a bean entity not a data access interface layer. Something like CommonDao:
public interface CommonDao {
//...
}
This class can be extended following your Entity type.
You may also need to revise your method signatures, e.g. deleting an entity should only need its identifier.
Update your class also to use Java Generics which will let you gain in reusability and make your class accept any entity type:
public interface CommonDao<T> {
T create(T entity);
//...
}
I highly recommand #sp00m solution.
Related
I'm building my first Spring Boot app using JPA and have setup my data repositories and services like this:
#Repository
public interface FooRepository extends JpaRepository<Foo, Long> {
Set<Foo> findAllByActiveInstallationIsNull();
}
Then a CrudService
public interface CrudService<T extends BaseEntity> {
Set<T> findAll();
T findById(Long id);
T save(T object);
void delete(T object);
void deleteById(Long id);
}
along with an example class service interface that extends it
public interface FooService extends CrudService<Foo> {
Set<Foo> findAllAvailable();
Foo getIfAvailable(Long id);
}
an abstract class for service implementations
public abstract class AbstractJpaService<T extends BaseEntity, R extends JpaRepository<T, Long>> implements CrudService<T> {
protected R repository;
public AbstractJpaService(R repository) {
this.repository = repository; }
#Override
public Set<T> findAll() {
return new HashSet<>(repository.findAll()); }
#Override
public T findById(Long id) {
return repository.findById(id).orElse(null); }
#Override
public T save(T object) {
return repository.save(object); }
#Override
public void delete(T object) {
repository.delete(object); }
#Override
public void deleteById(Long id) {
repository.deleteById(id); }
}
and finally an example of an actual service class that extends the above-mentioned one:
#Service
#Transactional
public class FooJpaService extends AbstractJpaService<Foo, FooRepository> implements FooService {
public FooJpaService(FooRepository repository) {
super(repository);
}
///
}
I wrote some service layer logic, controllers and once I was happy with the first iteration I've done some postman testing that worked without a hitch.
Then I took a step back and started writing some unit tests for my service classes only to realize that while findAll() in my services returns Set as I intended, the JpaRepository methods and by extension my own repos give List.
#Test
void findAll() {
Set<Foo> returnFooSet = new HashSet<>();
returnFooSet.add(new Foo(boo, 1d, 2d));
returnFooSet.add(new Foo(baz, 3d, 4d));
when(fooRepository.findAll()).thenReturn(returnFooSet);
Set<Foo> foos = service.findAll();
assertNotNull(foos);
assertEquals(2, foos.size());
}
resulting in thenReturn() method expecting a List.
Sorry for the wall of code, but I'm pretty new at this and very much confused so figured I'll provide excessive context even if most could have been assumed, since my newbie implementations may be weird and faulty.
So what gives?
I've read about the benefits of using Sets in JPA and most of the code examples I've seen use them.
My own findAllByArgument methods with Set returns like the ones you see in the repository have been working just fine, so I assume nothing stops me from overriding basic FindAll() methods in all of my repos (since CrudRepository seems to have just Iterable there), but that seems... off?
Should I be using Sets with JPA? What are good practices in this case?
I believe the only rule of thumb regarding List or Set in JPA world (with Hibernate under the hood) is to always use Set on a #ManyToMany relationship and never List.
Other than that I am not aware of anything else. Still, I can guess that maybe Set is better in terms of performance since it is unordered while List is ordered. Given that JpaRepository has a method that returns List this eventually better performance might not be relevant enough.
i have a few DAOs in my app which access a database for CRUD operations. Lets say there News, weather and , sports DAO. So im confused on how many Repositories i would need. should i just use one repository say DataRepository and let me hold my database and all dao's. and encapsulate methods for the CRUD operations in it ? or should each DAO have its own repository ?
I mean a repository should return only data objects that the calling layer understands. so its like a encapsulation over the DAOs but im not sure if i should create one per DAO or just have one repo per app, etc.
If you read this article we begin to understand that the pattern is over engineered or over abstracted. Its turned into hiding detail vs minimizing query statements.
But it seems There should be a Repo per DAO as the interface itself looks like this:
interface Repository<T> {
void add(T item);
void remove(Specification specification);
List<T> query(Specification specification);
}
where T can be the type/table of data DAO accesses. Just need clarification now. Can you imagine i have 30 different types, so then i need 30 different Repo implementations. this is ridiculous. It seems the repository pattern itself is like a DAO, no different. im so confused.
I am not sure this is what all you looking for but In my application I am using described DAO pattern with Spring
So im confused on how many Repositories i would need.
IMHO you will need at least single Repository for each entity as they lead to simple design but since you are making them generic and they are up in hierarchy, can be used simply with child classes/interfaces
Below is the example
Interface to define all basic methods that to use commonly
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, LockModeType lock);
void save(T entity);
T update(T entity);
List<T> findAll();
}
Generic Implementation
public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {
#PersistenceContext
protected EntityManager em;
private final Class<T> entityClass;
public GenericDAOImpl(Class<T> entityClass) {
this.entityClass = entityClass;
}
#Override
public T findById(ID id, LockModeType lock) {
return em.find(entityClass, id, lock);
}
#Override
public void save(T entity) {
em.persist(entity);
}
#Override
public T update(T entity) {
return em.merge(entity);
}
#Override
public List<T> findAll() {
CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
c.select(c.from(entityClass));
return em.createQuery(c).getResultList();
}
.
.
.
}
Foo class
#Entity
public class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String text;
}
Foo Repositiry
public interface FooRepositiry extends GenericDAO<Foo, Long> {
Foo findTextById(Long id);
}
Implemented Foo Repositiry
#Transactional
#Repository
public class FooRepoImpl extends GenericDAOImpl<Foo, Long> implements FooRepositiry {
public FooRepoImpl() {
super(Foo.class);
}
#Override
public Foo findTextById(Long id) {
CriteriaQuery<Foo> c = em.getCriteriaBuilder().createQuery(Foo.class);
// .
// .
// .
return em.createQuery(c).getSingleResult();
}
}
Same for Bar class
#Transactional
#Repository
public class BarRepoImpl extends GenericDAOImpl<Bar, Long> implements BarRepo {
public BarRepoImpl() {
super(Bar.class);
}
#Override
public List<Bar> findAllBarWithText(String text) {
CriteriaQuery<Bar> c = em.getCriteriaBuilder().createQuery(Bar.class);
return em.createQuery(c).getResultList();
}
}
Here this generic implementation needs two things to work: an EntityManager and an
entity class. A subclass must provide the entity class as a constructor argument. EntityManager is provided by using PersistenceContext or you can use getter-setter methods for the same. Since GenericDAOImpl is abstract threfore you cannot use it directly but Indirectly and most of the commnoly used methods are generic and up in hierarchy which makes them Ideal candidate to be reused.
You can read more about this from book Java Persistence with Hibernate 2nd Edition
In my current spring setup i would like to implement a slightly different architecture, here is my setup:
I have a "base" DAO interface, which lists all CRUD operations:
public interface BaseDao {
public boolean create(Object obj);
public List<Object> read();
public boolean update(Object obj);
public boolean delete(Object obj);
}
Next i have "specific" DAO interface, which extends from the "base" one:
public interface ArticleDao extends BaseDao {
public List<Article> getArticlesByAttribute(String attribute);
}
And finally, the Repository, which implements the interface:
public class ArticleDaoImpl implements ArticleDao {
public boolean create(Article article) {
// code
}
public List<Article> read() {
// code
}
public boolean update(Article article) {
// code
}
public boolean delete(Article article) {
// code
}
public List<Article> getArticlesByAttribute(String attribute) {
// code
}
}
So the idea is simple:
I want every Repository to implement all crud operations + "the methods from the specific dao-interface"
But i get the following error:
ArticleDaoImpl is not abstract and does not override
abstract method delete(java.lang.Object) in BaseDao
etc..
So this is probably because i defined Object as a parameter in the interface and "Article" as a parameter in the actual implementation..
Anybody got the idea how i can follow this pattern correctly?
Should i consider working with generics?
Thanks and Greetings
No. You should work with Spring Data JPA/MongoDB etc. It will make MOST of your boilerplate code go away. Seriously - forget about DAO and go with Spring Data JPA: https://spring.io/guides/gs/accessing-data-jpa/
I'm developing a web application with spring framework and mybatis.
In most cases(at least for me), DAO's methods are very short something like this:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User) getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
So basically, I need to write a method(e.g. getUser(String userId)) in DAO for each query which is being forwarded to service objects where it is being used. It seems unnecessarally redundunt to me.
My co-worker is trying to make it simple. He wrote CommonDao like this:
#Repository
public class CommonDao {
#Autowired
private SqlSessionTemplate sqlSession;
public Object insert(String queryId, Object params) {
return sqlSession.insert(queryId, params);
}
public Object update(String queryId, Object params) {
return sqlSession.update(queryId, params);
}
public Object delete(String queryId, Object params) {
return sqlSession.delete(queryId, params);
}
public Object selectOne(String queryId) {
return sqlSession.selectOne(queryId);
}
public Object selectOne(String queryId, Object params) {
return sqlSession.selectOne(queryId, params);
}
}
So we can use these methods in services like:
#Service
public class CrudService {
...
#Autowired
private CommonDao commonDao;
...
public UserDto selectUser(Integer userId) {
...
UserDto userDto = (UserDto) commonDao.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
...
}
}
I'm kinda like this approch since it makes codes simpler. But I'm not sure it is a good prectice to follow.
To avoid a boilerplate code and at the same time have type safety and leave your service layer free from DAO implementation details use spring-mybatis MapperScannerConfigurer.
In this case you can replace your DAOs with type-safe mappers.
The equivalent of your DAO
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User)getSqlSession().selectOne(
"org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
will be this mapper class
package org.mybatis.spring.sample.mapper;
interface UserMapper {
User getUser(String userId);
}
If you rename it to UserDao you will not need to change your services at all. Service only depends on the declared mapper interface.
Note that you need to define this interface in order to have type safety and also define the dependency of you service.
Of course you need configure spring-mybatis so that it generates mapper implementation based on the mapper interfaces defined in your code. This is rather straightforward and there are many options how to do that.
Hmm, what you are struggling with, is normal in MyBatis.
Your co-worker pointed you in some direction... But what is the real value of CommonDao in this shape? For me it's not very useful. You still need almost the same amount of code - and still you have to do a lot of casting.
As #Rom Konoval said, there is MapperScannerConfigurer which can generate mapper implementations - this way you don't write redundant implementations and have the benefit of a type safety - type casting still happens but is hidden from you. You can try it.
Here is a sample usage on the GitHub.
Alternatively, you can create DAO implementations by yourself (as you already did) or just use the SqlSessionTemplate directly in your Services. Up to you. Just keep your code base as small as possible and follow a common sense.
I'm trying to create a good OOP design especially conforming to SRP for interfacing with a database to insert and delete Customers. My focus is on design rather than getting bogged down by details of SQL and JDBC or datasources. So I've left simple implementations using printlines. But I'm wondering if this is how springs jdbctemplate is designed..
This effort came about while I was learning about the SRP OOP design principle. A poorly designed Customer class violated SRP since it contained database insert/delete responsibility. I pulled out code from Customer class and put it into a class that inherits from an RdbmsManager base class who's responsibility is to establish connections and interact with the database. I'm not sure about weather this is a good design, and I'm also not sure if some database API object similar to jdbcTemplate or something needs to be provided to child classes to interact with the database.
Customer class
public class Customer {
private int id;
private String fullName;
private boolean active;
public Customer(int id, String name, boolean active){
this.id = id;
this.fullName = name;
this.active = active;
}
#Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", active=" + active
+ "]";
}
}
The parent database access class:
public class RdbmsManager{
public RdbmsManager(){
connectToDatabase();
}
private void connectToDatabase(){
// read from properties files to get DB URL, PORT number etc.
// Create Datasource object and establish connection to database
System.out.println("Established Database Connection...");
}
// Below method returns the database object children can use to issue commands
protected DatabaseAPI getDatabaseObject(){
DatabaseAPI databaseObject = new DatabaseAPI ();
return databaseObject;
}
}
CustomerDataManager child class:
public class CustomerDataManager extends RdbmsManager{
public CustomerDataManager() {
super(); // call to super will establish database connection from parent class
}
public void saveCustomerToDatabase(Customer Customer) {
getDatabaseAPI().insert(Customer);
}
public void deleteCustomerFromDatabase(Customer Customer) {
getDatabaseAPI().delete(Customer);
}
}
Simple implementation for the database interaction object to focus on design:
public class DatabaseAPI{
protected void insert(Object object){
System.out.println("inserted the into the database: "+ object.toString());
}
protected void delete(Object object){
System.out.println("Deleted object from database" + object.toString());
}
}
Well, you're pretty close to what is one of the standard designs to working with databases.
The main difference is in the name of the classes (e.g. DAO instead of Manager), and that you are extending the DB connection pool manager in order to create the DAOs.
Let me elaborate a little bit:
The database should be separated by abstraction from your application. In order to achieve this, you usually create what's known as a data abstraction layer on top of the database. This is a little bit similar to your RdbmsManager class, and its point is to abstract away the actual DB used. In order to achieve this, you normally have a database access interface of some kind which will be implemented by some class controlling all connections to the DB (try to avoid names containing 'Manager' since it doesn't really help clarify what those classes do). If later on you decide to change the DB you're using, all you need to do is create a new implementation to the interface that supports the new DB, and you're pretty much done !
Access to the actual data in the database should also be abstracted by another layer, usually called data access layer. This layer contains interfaces that encapsulate all access to specific type of data (per table usually), and enable CRUD operations to be performed on them. Those interfaces are generally named SomethingDAO where 'Something' stands for the type of object being accessed (the 'DAO' part stands for: 'Data Access Object'). Again, the implementations of those interfaces should be DB specific and be changed when you replace the DB you use with another.
The data should be transferred to the client code (usually the business/application layer) using some other method, usually DTOs (stands for 'Data Transfer Object'). These are (again) interfaces which expose some functionality required from the objects being represented in the DB, which should be implemented by DB specific (or generic, it depends) classes.
This is the theory in short. There are many data sources online (not to mention books) that will allow you to read much more about it.
On a different note, this is just one way to implement DB connectivity. There are numerous others, since there are a lot of design patterns that refer to enterprise applications in general, and to inter-tier communications in particular. Let me refer you to what I consider the best source for those design patterns: Patterns of Enterprise Application Architecture
Edit 1:
Here's a really simplistic code example (untested of course - treat as pseudo code):
public interface Customer { ... }
public interface CustomerDTO implements Iterable<Customer> { ... }
public class CustomerDTOSQLImpl {
public CustomerDTOSQLImpl(ResultSet resultSet) { ... }
#Override
public Iterator<Customer> iterator() { ... }
...
}
public interface CustomerDAO {
public CustomerDTO findById(int id);
...
}
public class CustomerDAOSQLImpl {
#Inject
private Connection connection;
#Override
public CustomerDTO findById(int id) {
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMER WHERE ID = ?");
statement.setInt(1, id);
return new CustomerDTOSQLImpl(statement.executeQuery());
}
...
}