Eclipse dao component implement error - java

I have been working on spring+hibernate+mysql integration recently.For that, I try to build a basic program that adds, edits, deletes and searches students.I have firstly created model class and added necessary JPA annotations:
package com.joseph.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Student {
#Id
#Column
#GeneratedValue(strategy=GenerationType.AUTO) // for autonumber
private int studentId;
#Column
private String firstname;
#Column
private String lastname;
#Column
private int yearLevel;
public Student(){}
public Student(int studentId, String firstname, String lastname,
int yearLevel) {
super();
this.studentId = studentId;
this.firstname = firstname;
this.lastname = lastname;
this.yearLevel = yearLevel;
}
/* Getters and Setters */
}
Then I constructed DAO interface:
package com.joseph.dao;
import java.util.List;
import com.joseph.model.Student;
public interface StudentDao {
public void add(Student student);
public void edit(Student student);
public void delete(int studentId);
public Student getStudent(int studentId);
public List getAllStudent();
}
To get the necessary data from SQL, I implemented the dao interface as follows:
package com.joseph.dao.impl;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.joseph.dao.StudentDao;
import com.joseph.model.Student;
#Repository
public class StudentDaoImpl implements StudentDao {
#Autowired
private SessionFactory session;
#Override
public void add(Student student) {
session.getCurrentSession().save(student);
}
#Override
public void edit(Student student) {
session.getCurrentSession().update(student);
}
#Override
public void delete(int studentId) {
session.getCurrentSession().delete(getStudent(studentId));
}
#Override
public Student getStudent(int studentId) {
return (Student)session.getCurrentSession().get(Student.class, studentId);
}
#Override
public List getAllStudent() {
return session.getCurrentSession().createQuery("from Student").list();
}
}
But I have error at add(Student student) method at StudentDaoImpl.java class that says:
Multiple markers at this line
- The method add(Student) of type StudentDaoImpl must override or implement a supertype method
- implements com.joseph.dao.StudentDao.add
This error is similar for all other methods in the same class.
How can I fix this?

You should remove the public from the methods on the Interface:
package com.joseph.dao;
import java.util.List;
import com.joseph.model.Student;
public interface StudentDao {
void add(Student student);
void edit(Student student);
void delete(int studentId);
Student getStudent(int studentId);
List getAllStudent();
}

Your code is 100% working, under my test enviroment (InteliJ, JDK7+), so it is connected with your IDE purely.
Try to restart your IDE or reimport this project.
I could share also some tips:
use Long instead of int, when creating model id's
you don't need to add #Column annotation next to #Id, #Id will do alone
inside your parametrized constructor (Student), you don't need to add super(), compiler will add it automatically, seconsly your upper class is Object, so there is no need for that line :)
using such approach would couse lots of code duplication when you will be using many dao, you could use inheritance here, like so:
Here is example of generic DAO class:
public class GenericDaoImpl <D>{
protected SessionFactory session;
protected Class clazz;
public GenericDaoImpl(SessionFactory session, Class clazz){
this.session = session;
this.clazz = clazz;
}
#Override
public void add(D entity) {
session.getCurrentSession().save(entity);
}
#Override
public void update(D entity) {
session.getCurrentSession().update(entity);
}
#Override
public void remove(Long id) {
session.getCurrentSession().delete(get(id));
}
#Override
public Student get(Long id) {
return (Student)session.getCurrentSession().get(clazz, id);
}
#Override
public List getAll() {
return session.getCurrentSession().createQuery("from " + clazz.getSimpleName()).list();
}
}
To create StudentDao, simply do so:
public interface StudentDao{
void add(Student student);
void update(Student student);
void remove(int id);
Student get(int id);
List getAll();
}
And finally your Dao implementation:
public class StudentDaoImpl extends GenericDaoImpl<Student> implements StudentDao{
#Autowired
public StudentDaoImpl(SessionFactory sessionFactory){
super(sessionFactory, Student.class);
}
}
With this approach you could reuse most of this code in all Dao :) So less code to maintain, easy to use.

Related

How can I implement the Repository pattern using Generic Types with Java Spring

I am trying to find a way I can implement the repository pattern using spring boot with Generic types. So far I looked into this article:
https://thoughts-on-java.org/implementing-the-repository-pattern-with-jpa-and-hibernate/
and tried implementing this solution using generic types based on the solution to this question:
Using generics and jpa EntityManager methods
I attempted to do so using JPA and Hibernate but for me, an error appears when I try returning the class of the entity on the specified type parameter.
the following is my User model using JPA and Hibernate:
package models;
import javax.persistence.*;
#Entity
public class User extends Model {
#Id
#Column(name = "id", updatable = false, nullable = false)
private String id;
public String username;
private String password;
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
public String getPassword() {
return password;
}
}
The following is my interface for basic CRUD operations:
package repositories;
import models.Model;
import java.util.UUID;
public interface IRepository<T> {
void add(T entity);
void delete(String id);
void update(T entity);
T get(String id);
boolean exists(String id);
}
I then created an abstract class for all repositories to avoid repeating myself for all Models.
package repositories;
import models.Model;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
public abstract class Repository<T> implements IRepository<T>{
private EntityManager em;
public Repository(EntityManager em){
this.em = em;
}
#Override
public void add(T entity) {
em.persist(entity);
}
#Override
public void delete(String id) {
T entity = get(id);
em.remove(entity);
}
#Override
public void update(T entity) {
em.merge(entity);
}
#Override
public T get(String id) {
return em.find(getEntityClass(), id);
}
public boolean exists(String id) {
return em.contains(get(id));
}
// link to an explanation can be found at:https://stackoverflow.com/questions/40635734/using-generics-and-jpa-entitymanager-methods
// when a class extends this class, all is needed is to fill out the method body of to return the class.
public abstract Class<T> getEntityClass();
}
the abstract class is there for me to return the class that belongs to T
and this is the specific repository for Users:
package repositories;
import models.Model;
import models.User;
import javax.persistence.EntityManager;
public class UserRepository<User> extends Repository<User> {
public UserRepository(EntityManager em) {
super(em);
}
#Override
public Class<User> getEntityClass() {
return null;
}
}
Ideally, for the getEntityClass method, I would like to return User.class, but I get an error on the IDE saying "Cannot select from type variable". I have looked at a few more questions online and another thing people tried was either put a parameter of type Class or have a member of type Class within the User repository. I tried both methods and it didn't work, any ideas?
class UserRepository<User> should just be class UserRepository. Otherwise, User is just like T, a generic type. Not the class User.
But you're reinventing the wheel. Learn and use Spring Data JPA, which brings generic repositories, and more.

How to implement generic service-layer class in Spring Framework?

I try to implement generic service-layer class for basic CRUD operations.
public abstract class AbstractService<T, R extends JpaRepository> {
protected R repository;
public AbstractService(R repository) {
this.repository = repository;
}
public T getOne(final Long id){
return repository.findById(id); // error Required: T, Found: Optional<>
}
}
Why couldnt I use type T without wrapping it to Optional?
You should always follow the good practices that are recommended for JPA and hibernate, so you must create a respository per entity, as this will allow you to develop more scalable applications, however if you want not to have to do this and want an abstract class that allows you To do this, I recommend doing an abstract Dao class that allows you to perform CRUD operations as follows:
import java.io.Serializable;
import java.util.List;
/**
* #author Edy Huiza
* #version 1.0
* Created on 23/11/2018
*/
public interface Dao<T> {
void persist(Object entity);
void persist(Object[] entities);
void update(Object entity);
void delete(Object entity);
void delete(Class entityClass, Serializable id);
List findAll(Class entityClass);
Object get(Class entityClass, Serializable id);
}
And their respective implementation
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
/**
* #author Edy Huiza
* #version 1.0
* Created on 23/11/2018
*/
#Repository
public class SpringHibernateDao implements Dao {
#PersistenceContext
private EntityManager entityManager;
#Override
#Transactional
public void persist(Object entity) {
entityManager.persist(entity);
entityManager.flush();
entityManager.clear();
}
#Override
#Transactional
public void update(Object entity) {entityManager.merge(entity);
}
#Override
#Transactional
public void persist(Object[] entities) {
for (Object entity : entities) {
persist(entity);
}
}
#Override
#Transactional
public void delete(Object entity) {
entityManager.remove(entity);
}
#Override
#Transactional
public void delete(Class entityClass, Serializable id) {
Object entity = get(entityClass, id);
entityManager.remove(entity);
}
#SuppressWarnings("unchecked")
#Override
#Transactional(readOnly = true)
public List findAll(Class entityClass) {
return entityManager.createQuery("from " + entityClass.getName()).getResultList();
}
#Override
#Transactional(readOnly = true)
public Object get(Class entityClass, Serializable id) {
return entityManager.find(entityClass, id);
}
}
And their respective use
#Autowired
Dao dao;
#Override
#Transactional(readOnly = true)
public Dispositivo get(long id) {
return (Dispositivo) dao.get(Dispositivo.class, id);
}
You can try something like this:
public abstract class AbstractService<T, ID, R extends JpaRepository<T, ID>> {
protected R repository;
public AbstractService(R repository) {
this.repository = repository;
}
public Optional<T> getOne(ID id){
return repository.findById(id);
}
}

Does not persist entity to db

When I try to add data to the database, the hibernate hangs on this point.
Hibernate: select next_val as id_val from hibernate_sequence for update
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Domain class
package org.jazzteam.domain.commentary;
import org.jazzteam.domain.id.Id;
import org.jazzteam.domain.event.Event;
import org.jazzteam.domain.user.SimpleUser;
import org.jazzteam.domain.user.User;
import javax.persistence.*;
/**
* #author Yura
* #version 1.0
*/
#Entity
#Table
public class Commentary extends Id {
#OneToOne(cascade = CascadeType.ALL)
private SimpleUser author;
private String description;
/*#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Event event;*/
private int rating;
public Commentary(){
}
public Commentary(SimpleUser author, String description, Event event, int rating){
this.author = author;
this.description = description;
/*this.event = event;*/
this.rating = rating;
}
public void setAuthor(SimpleUser author) {
this.author = author;
}
public void setDescription(String description) {
this.description = description;
}
/*public void setEvent(Event event) {
this.event = event;
}*/
public void setRating(int rating) {
this.rating = rating;
}
public User getAuthor() {
return author;
}
public String getDescription() {
return description;
}
/*public Event getEvent() {
return event;
}*/
public int getRating() {
return rating;
}
}
DAO
package org.jazzteam.dao.commentary;
import org.hibernate.SessionFactory;
import org.jazzteam.domain.commentary.Commentary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* Created by Yura on 14.04.2017.
*/
#Repository
public class CommentaryDaoImpl implements CommentaryDao<Commentary> {
#Autowired
SessionFactory sessionFactory;
#Override
public void persist(Commentary entity) {
sessionFactory.getCurrentSession().persist(entity);
}
#Override
public void update(Commentary entiry) {
sessionFactory.getCurrentSession().update(entiry);
}
#Override
public void delete(Commentary entity) {
sessionFactory.getCurrentSession().delete(entity);
}
#Override
public Commentary findById(int id) {
return sessionFactory.getCurrentSession().get(Commentary.class, id);
}
#Override
public List<Commentary> findAll() {
return sessionFactory.getCurrentSession().createQuery("from Commentary ").list();
}
}
Service class
package org.jazzteam.service.commentary;
import org.jazzteam.dao.commentary.CommentaryDao;
import org.jazzteam.domain.commentary.Commentary;
import org.jazzteam.service.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by Yura on 14.04.2017.
*/
#org.springframework.stereotype.Service
public class CommentaryService implements Service<Commentary> {
#Autowired
CommentaryDao commentaryDao;
#Transactional
public void persist(Commentary entity) {
commentaryDao.persist(entity);
}
#Transactional
public void update(Commentary entity) {
commentaryDao.update(entity);
}
#Transactional
public void delete(int id) {
commentaryDao.delete(commentaryDao.findById(id));
}
#Transactional
public Commentary findById(int id) {
return (Commentary) commentaryDao.findById(id);
}
#Transactional
public List<Commentary> findAll() {
return commentaryDao.findAll();
}
}
I'm trying to add with this:
Commentary commentary = new Commentary(simpleUserService.findById(idAuthor),
comment,
eventService.findById(idEvent),
rate);
commentaryService.persist(commentary);
Id generate by class ID:
package org.jazzteam.domain.id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.MappedSuperclass;
/**
* #author Yura
* #version 1.0
*/
#MappedSuperclass
public abstract class Id {
#javax.persistence.Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected int id;
public Id() {
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
What could be my mistake?
looks like you're trying to reinvent the wheel.
We might focus closely on your code, but I have a more general suggestion.
You already use Spring and Hibernate. Why not just use it as most people use it in 2017 - with Spring Data JPA.
You can google that and find lots of great tutorials about that topic.
Here is an official Spring introduction: https://spring.io/guides/gs/accessing-data-jpa/
a GitHub project with some examples: https://github.com/spring-projects/spring-data-examples
and a reference: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
hope that helps :)
cheers
Solved this problem by changing:
#Override
public void persist(Commentary entity) {
sessionFactory.getCurrentSession().persist(entity);
}
to
#Override
public void persist(Commentary entity) {
sessionFactory.getCurrentSession().save(entity);
}
Perhaps it will be useful to someone :)

Unable to insert in table using hibernate

I'm using hibernate to create table and then i'm inserting the records in the table when application starts.
For inserting the record i'm using the last example of this page
Problem : Hibernate is able to create the tables but when i'm inserting the records at the application startup it is not getting inserted.
On the other hand if i use a REST service to do the same task it works perfectly fine.
Here is my JPA class.
package com.vizexperts.georbis.usermanagement.types;
import javax.persistence.*;
#Entity
public class TestMe {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long Id;
#Column
String name;
public TestMe(String name) {
this.name = name;
}
public Long getId() {
return Id;
}
public void setId(Long id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Here is corresponding TestMeRepository class.
package com.vizexperts.georbis.usermanagement.types;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface TestMeRepository extends CrudRepository<TestMe, Long> {
TestMe findByName(String name);
}
And this is how i'm inserting the data.
package com.vizexperts.georbis.config;
import com.vizexperts.georbis.usermanagement.types.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
public class InitialDataConfig implements ApplicationListener<ContextRefreshedEvent>{
#Autowired
TestMeRepository testMeRepository;
#Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
// Here newly saved object is returned as testMe
// when debugging i can see the auto generated **id** for
// testMe object.
TestMe testMe = testMeRepository.save(new TestMe("Test"));
}
}
And as i said if i use the following service it works.
#RequestMapping("/georbis/test")
public Response<Void> test(){
testMeRepository.save(new TestMe("working"));
return new Response<>(true, "working");
}
I think the reason is that you are missing #Component annotation on your InitialDataConfig class.
And that is why this class is not registered as a bean and onApplicationEvent method is never called.
Add the #Component annotation and it should work fine.
Alternately you can use CommandLineRunner, try this example.

JPA, Spring web - how to "find" non-existent record in database

I have web written in Spring. I use Hibernate for JPA. I need to find entity in database, I get ID from user.
Problem is if ID is not in database - I get a NullPointerException.
Now I have:
People p;
try {
p = peopleManager.findById(id);
if (p != null) {
model.addAttribute("message", "user exist, do any action");
} else {
model.addAttribute("message", "user NOT exist");
}
} catch (NullPointerException e) {
model.addAttribute("message", "user NOT exist");
}
but it looks terrible. How can I do it right?
There is complete example code:
package com.example.test.entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class People {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name="name")
private String name;
#Column(name="age")
private int age;
}
/* ---------------------------------------------------- */
package com.example.test.dao;
import java.util.List;
import com.example.test.entity.People;
public interface PeopleDao {
public void save(People people);
public void delete(People people);
public void update(People people);
public List<People> findAll();
public People findById(int id);
}
/* ---------------------------------------------------- */
package com.example.test.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.example.test.entity.People;
#Repository
public class PeopleDaoImpl implements PeopleDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void save(People people) {
this.sessionFactory.getCurrentSession().save(people);
}
#Override
public void delete(People people) {
this.sessionFactory.getCurrentSession().delete(people);
}
#Override
public void update(People people) {
this.sessionFactory.getCurrentSession().update(people);
}
#Override
public List<People> findAll() {
return this.sessionFactory.getCurrentSession().createQuery("from People ORDER BY age").list();
}
#Override
public People findById(int id) {
return (People) this.sessionFactory.getCurrentSession().get(People.class, id);
}
}
/* ---------------------------------------------------- */
package com.example.test.service;
import java.util.List;
import com.example.test.entity.People;
public interface PeopleManager {
public void save(People people);
public void delete(People people);
public void update(People people);
public List<People> findAll();
public People findById(int id);
}
/* ---------------------------------------------------- */
package com.example.test.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.test.dao.PeopleDao;
import com.example.test.entity.People;
#Service
#Transactional
public class PeopleManagerImpl implements PeopleManager {
#Autowired
private PeopleDao peopleDao;
#Override
public void save(People people) {
peopleDao.save(people);
}
#Override
public void delete(People people) {
peopleDao.delete(people);
}
#Override
public void update(People people) {
peopleDao.update(people);
}
#Override
public List<People> findAll() {
return peopleDao.findAll();
}
#Override
public People findById(int id) {
return peopleDao.findById(id);
}
/* ---------------------------------------------------- */
package com.example.test.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.test.entity.People;
import com.example.test.service.PeopleManager;
#Controller
public class PeopleController {
#Autowired
private PeopleManager peopleManager;
#RequestMapping(value = "/people/{id}", method = RequestMethod.GET)
public String home(Model model, #PathVariable("id") String id) {
People p;
try {
p = peopleManager.findById(Integer.parseInt(id));
if (p != null) {
model.addAttribute("message", "user exist, do any action");
} else {
model.addAttribute("message", "user NOT exist");
}
} catch (NullPointerException e) {
model.addAttribute("message", "user NOT exist");
}
return "people";
}
}
/* ---------------------------------------------------- */
Refactor the null check out of your controller. Controllers shouldn't have any business logic in them. The correct place for this is inside your service class.
#Override
#Transactional
public People findById(int id) throws ObjectNotFoundException{
People people = null;
people = peopleDao.findById(id);
if(people == null){
throw new ObjectNotFoundException("Couldn't find a People object with id " + id);
}
return people;
}
I would write a custom exception that extends RuntimeException that is thrown if your People object is null.
This is best practice as you can reuse your ObjectNotFoundException in all your service layers. Then make all your controller methods throw Exception and investigate global error handling for controllers.
Also, it is best practice to not annotate your entire service class as #Transactional, mark the individual methods. That way if you need to add additional methods to your services you can choose if you want them to run in a transactional context.

Categories