Spring data JPA not returning record while same exists in table - spring

I have an entity Student which has a column name username. I am trying to fetch a student in studentRepository with below method:
#Query("select x from Student x where x.userName=:userName")
Student findStudentByUserName(#Param("userName")String userName)
While the record exists in table, this method is returning null. To cross verify, I executed the query prepared by hiberante that is printed in logs. That returned the intended record as expected.
Can someone help me to understand the issue?
Thanks
Edit: as asked in comments, sharing repository class
package com.pinelabs.pineklik.repository.lead;
import java.util.List;
import java.util.Set;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
#Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
#Query("select x from Student x where x.userName=:userName")
Student findStudentByUserName(#Param("userName")String userName);
}
Forgot to mention that this works fine in all enviroment but dev/local machine.
Solution: My bad. Extremely ridiculous of me to have pointed to local db instead of test db which was causing the issue.

Remove the #Query and try this. This is assuming that there is a String field userName in Student entity class.
#Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Student findByUserName(String userName);
}

Related

JpaRepsotory custom query method executes but I can see no record updated in database table

I have the updatePassword interface which extends the JpaRepository -
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.erecruitment.app.model.user;
#Repository
public interface updatePassword extends JpaRepository<user, Long>{
public String nativeQuery="UPDATE user SET password=?1 WHERE username=?2";
#Transactional
#Modifying
#Query(value=nativeQuery,nativeQuery=true)
int updtPassword(String password,String username);
}
After application runs it give the following response in the console -
Hibernate:
UPDATE
user
SET
password=?
WHERE
username=?
But, the problem is when I check the database table the values are still same .Also ,there is no error from spring boot . Where am I going wrong?
That query looks good... maybe the problem somewhere else... Are you sure you connect ot the proper DB? (eg. You made some changes in the properties, or connect Spring connects to an autogenerated inmemory db, etc.)

MongoRepository Delete Method

Good afternoon fellow coders!
I have spent the last hour looking to delete a single document from my mongo "testCollection". I would like to make use of the MongoRepository delete / deleteAll methods. However, it does not remove the document. It persists regardless of how many times I run the test class method. No errors are reported and the user has readWrite permissions in the database. I am able to run the mongo command to remove the newly created test document.
I have read about using the mongo template and create it for the deletion to be performed. I'm happy to do that but I would rather keep it as simple as possible.
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;
#Data
#Document(collection = "testCollection")
public class TestClass {
#MongoId
private String id;
private String name;
public TestClass(String name) {
this.name = name;
}
}
Test Class Mongo Repository interface
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface TestClassRepository extends MongoRepository<TestClass, String> {
public List<TestClass> findAllByName(String name);
public void deleteAllByIdIn(List<TestClass> list);
}
Test Method
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
#RunWith(SpringRunner.class)
#TestPropertySource(value = {"classpath:application.properties"})
#AutoConfigureMockMvc
public class testClassTest {
#Autowired
private TestClassRepository testClassRepository;
#Test
public void crudTest() {
TestClass testObj = new TestClass("Test");
testClassRepository.save(testObj);
List<TestClass> testClassList = testClassRepository.findAllByName("Test");
Assert.assertEquals(1, testClassList.size());
TestClass test = testClassList.get(0);
testClassRepository.deleteAllByIdIn(testClassList);
// Fails this assertion: Found 1, expected 0.
Assert.assertEquals(0, testClassRepository.findAllByName("Test").size());
}
}
As anyone else experienced a similar issue? If so, how'd you go about resolving it?
Thanks!
Additions to original post:
Here is the mongo query generated by the MongoRepository. It appears that it is not actually adding the "remove" mongo command to the query. Query: { "name" : "Test"}, Fields: {}, Sort: {}
With a stroke of dumb luck I managed to figure out the issue. The problem was with the type of identifier annotation I was using. This explanation from another stackoverflow user (What is use of #MongoId in Spring Data MongoDB over #Id?) had me revisit this aspect of the model.
I switched the identifier annotation from #MongoId to #Id. Since I have both JPA and MongoDB annotations I needed to make sure I chose the one from the org.springframework.data.annotation package rather than the javax.persistance package.
Hope this explanation helps others!

Spring boot JPA repository committing code even if #Transactional placed in Service layer

See below spring boot code
I have used JPA repository.
Controller.
Service.
Repository
BaseController
package com.controller;
import com.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class BaseController {
#Autowired
private StudentService studentService;
#GetMapping(value = "/addStudent", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<String> base() {
studentService.save();
return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
}
}
StudentService.java
package com.service;
import com.model.Student;
import com.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service("studentService")
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentRepository studentRepository;
#Override
#Transactional
public Student save() {
Student student = new Student();
student.setFirstName("ABC");
student.setLastName("PQR");
studentRepository.save(student);
int i = 10 / 0; //Error code
return student;
}
}
StudentRepository
package com.repository;
import com.model.Student;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository("studentRepository")
public interface StudentRepository extends CrudRepository<Student, Long> {
public List<Student> findAll();
}
Application.properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
#maximum number of milliseconds that a client will wait for a connection
spring.datasource.hikari.connection-timeout = 20000
#minimum number of idle connections maintained by HikariCP in a connection pool
spring.datasource.hikari.minimum-idle= 10
#maximum pool size
spring.datasource.hikari.maximum-pool-size= 10
#maximum idle time for connection
spring.datasource.hikari.idle-timeout=10000
# maximum lifetime in milliseconds of a connection in the pool after it is closed.
spring.datasource.hikari.max-lifetime= 1000
#default auto-commit behavior.
spring.datasource.hikari.auto-commit =false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.jdbcUrl=jdbc:mysql://localhost:3306/demo?autoReconnect=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.show-sql=true
spring.jpa.properties..hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
After executing save method from StudentRepository, data get inserted
immediately into database. no rollback or any other isolation levels are
working in StudentServiceImpl.java even if Error code is there.
I have tried to set "spring.datasource.hikari.auto-commit =true" setting value true, Placed #Transaction at top of the StudentServiceImpl.java class but still it didn't worked.
You do not need to mess with any hikari settings, and certainly not with autoCommit(true) as this DISABLES transactions. Delete all these properties.
Where is the "error" in your code? Spring rolls back on unchecked exceptions being thrown (not checked ones or errors), I cannot see that in your code.
What behavior do you expect? It looks fine to me.
It's probably beacause of Open Jpa in View behaviour.
Write the following line in your properties file:
spring.jpa.open-in-view=false
take a look at this if you want to know more.

In Spring boot application is #Component annotation optional for repo

I have created the basic application using Spring boot using JPA. I have added #AutoWired annotation for RatingRepo in RatingResource, but haven't added #Component annotation to RatingRepo
package com.example.demo;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.RatingsRateService.model.Rating;
import com.example.demo.RatingsRateService.model.UserRating;
#RestController
#RequestMapping("ratingsdata")
public class RatingResource {
#Autowired
RatingRepo repo;
/*
* #RequestMapping("/{movieId}") public Rating
* getRating(#PathVariable("movieId") String movieId) { return new
* Rating(movieId,7); }
*/
#RequestMapping("users/{userid}")
public UserRating getRating(#PathVariable("userid") int userid) {
List<Rating> ratings =repo.findByUserId(userid);
/*
* List<Rating> ratings = Arrays.asList(new Rating("1",4), new Rating("2",3),
* new Rating("3",2));
*/
System.out.println(ratings);
UserRating userRating = new UserRating();
userRating.setUserRating(ratings);
return userRating;
}
}
package com.example.demo;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.example.demo.RatingsRateService.model.Rating;
//to update the data in database , created the interd=face and will implement
//class,primary key
public interface RatingRepo extends JpaRepository<Rating, Integer>{
#Query(" from Rating where userid = ?1")
List<Rating> findByUserId( int userid);
}
. Still, it is working fine. Can you someone please explain why it is so? Or it is not needed to add #Component annotation for the repo?
first of there is #Repository annotation required not #Component
and #Repository also auto configure due to below:
Probably you are using spring boot
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you are using auto-configuration, repositories will be searched from the package containing your main configuration class (the one annotated with #EnableAutoConfiguration or #SpringBootApplication) down.
ref: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-spring-data-jpa-repositories

Implementation of DAO vs JPA

I would like to know the difference between JPA and Hibernate. I have read the very interesting question posted by #Anthony with interest but still I do not understand the full picture.
I have implemented my application in Spring MVC and Hibernate (see below). My DAOs are an implementation of services which have been built using HQL queries.
#Service("messagesService")
public class MessagesService
{
private MessagesDAO messagesDAO;
#Autowired
public void setMessagesDAO(MessagesDAO messagesDAO)
{
this.messagesDAO = messagesDAO;
}
public List<Message> getAllMessages()
{
return messagesDAO.getAllMessages();
}
...
--------
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
#Repository
#Transactional
#Component("messagesDAO")
public class MessagesDAO
{
#Autowired
private SessionFactory sessionFactory;
public Session session()
{
return sessionFactory.getCurrentSession();
}
#SuppressWarnings("unchecked")
public List<Message> getAllMessages()
{
Criteria crit = session().createCriteria(Message.class);
crit.createAlias("usernameSender", "u").add(Restrictions.eq("u.enabled",true));
return crit.list();
}
...
I really like the statement "JPA is the dance, Hibernate is the dancer." but in my specific case I do not fully get why my example is not JPA. MessageService is the dance and MessagesDAO the dancer(Implementation).
As #Kevin states:
Think of JPA as the guidelines that must be followed or an interface,
while Hibernate's JPA implementation is code that meets the API as
defined by the JPA specification and provides the under the hood
functionality.
I know I have not defined my service as an interface but this still lets me think that my code complies with the JPA specification requirements.
Now a concern arises
What is the difference between my example and the following from the pet clinic example
package org.springframework.samples.petclinic.repository;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
public interface PetRepository {
List<PetType> findPetTypes() throws DataAccessException;
-------
#Repository
public class JpaPetRepositoryImpl implements PetRepository {
#PersistenceContext
private EntityManager em;
#Override
#SuppressWarnings("unchecked")
public List<PetType> findPetTypes() {
return this.em.createQuery("SELECT ptype FROM PetType ptype ORDER BY ptype.name").getResultList();
}
The reason why I am asking all this questions is because I am using MySql in my application and I am thinking to change it in the future.
Therefore, I am trying to build my implementation layer to avoid any problem later on.
I was looking at nosql options and I discovered spring data jpa for the integration layer. I then started to learn a bit more about JPA and DAOs and the questions above suddenly arose
If I implement spring data jpa, can I use MySql for the moment and change it later to another database (Cassandra, MongoDb)?
What is the difference between Spring data JPA and Spring Data Mongodb
(The first is the specification and the second one the implementation?)
Thank you for your help
To keep the terminology: In your DAO you can't change your dancing partner.
Why? Because you are referencing Hibernate explicitly. If you would like to change the dancer some day you would have to change your whole implementation. Thats why you usually use only classes of the dance - JPA or Spring Data in your case.

Resources