February 21st, 2023
JUnit with JPA
JUnit test cases for the Repositories
Project Structure for adding Test files
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.0.2
com.brains.jpa.hibernate
jpa-hibernate-demo
0.0.1-SNAPSHOT
jpa-hibernate-demo
Demo project for Spring Boot
17
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
com.h2database
h2
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
application.properties
spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=USER;DB_CLOSE_ON_EXIT=FALSE
spring.h2.console.enabled=true
#spring.data.jpa.repositories.bootstrap-mode=default
spring.jpa.defer-datasource-initialization=true
# Turn Statistics ON
spring.jpa.properties.hibernate.generate_statistics=true
logging.level.org.hibernate.stat=debug
logging.level.org.hibernate=debug
# Show all queries
spring.jpa.show-sql=true
# Format the queries
spring.jpa.properties.hibernate.format_sql=true
# Enable seeing the parameters with query
logging.level.org.hibernate.type=trace
data.sql
insert into course(id, name) values(10001, 'JPA in 5 steps');
insert into course(id, name) values(10002, 'JDBC in 10 steps');
insert into course(id, name) values(10003, 'JPQL in 50 steps');
package com.brains.jpa.hibernate.jpahibernatedemo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Course {
@Id
@GeneratedValue
private Long id;
private String name;
public Course(String name) {
this.name = name;
}
}
EntityManager – An interface to the PersistentContext. PersistentContext keeps tracks of the entities which are changed during transactions.
@Transactional – For making any changes to the database, this annotation needs to be enabled.
- em.persist(Object) – saves the data, after this all the transactions are automatically saved and stored in the database
- em.flush() – sends the data to the database
- em.refresh() – get the data from the database
- em.clear() – Clears the memory cache of EntityManager
- em.detach(Object) – Detaches the object from the EntityManager cache memory and changes to the entity are no longer tracked.
package com.brains.jpa.hibernate.jpahibernatedemo.repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.brains.jpa.hibernate.jpahibernatedemo.entity.Course;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
@Repository
@Transactional
public class CourseRepository {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
EntityManager em;
public Course findById(Long id) {
return em.find(Course.class, id);
}
public void deleteById(Long id) {
Course course = findById(id);
em.remove(course);
}
public Course save(Course course) {
if(course.getId() == null) {
//insert
em.persist(course);
}else {
//update
em.merge(course);
}
return course;
}
public void playWithEntityManager() {
logger.info("playWithEntityManager - start");
Course course1 = new Course("AngularJs in 100 Steps");
em.persist(course1);
em.flush();
course1.setName("AngularJs in 100 Steps -- updated");
em.refresh(course1);
Course course2 = new Course("Microservices in 50 Steps");
em.persist(course2);
em.flush();
course2.setName("Microservices in 50 Steps -- updated");
}
}
package com.brains.jpa.hibernate.jpahibernatedemo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.brains.jpa.hibernate.jpahibernatedemo.repository.CourseRepository;
@SpringBootApplication
public class JpaHibernateDemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(JpaHibernateDemoApplication.class, args);
}
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CourseRepository courseRepository;
@Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
logger.info("FindById 10001: -> {}", courseRepository.findById(10001L));
courseRepository.playWithEntityManager();
}
}
package com.brains.jpa.hibernate.jpahibernatedemo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class JpaHibernateDemoApplicationTests {
@Test
void contextLoads() {
}
}
@SpringBootTest(classes = JpaHibernateDemoApplication.class)
This will load the SpringContext of the defined class on application startup. Run this file as “JUnit Test”.
@DirtiesContext – Resets the database for other methods
package com.brains.jpa.hibernate.jpahibernatedemo.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import com.brains.jpa.hibernate.jpahibernatedemo.JpaHibernateDemoApplication;
import com.brains.jpa.hibernate.jpahibernatedemo.entity.Course;
@SpringBootTest(classes = JpaHibernateDemoApplication.class)
class CourseRepositoryTest {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
CourseRepository courseRepository;
@Test
void find_by_id() {
Course course = courseRepository.findById(10001L);
assertEquals("JPA in 5 steps", course.getName());
}
@Test
@DirtiesContext
void delete_by_id() {
courseRepository.deleteById(10002L);
assertNull(courseRepository.findById(10002L));
}
@Test
@DirtiesContext
void save() {
// getById 10001
Course course = courseRepository.findById(10001L);
assertEquals("JPA in 5 steps", course.getName());
// update course
course.setName("JPA in 5 steps -- updated");
courseRepository.save(course);
// check the value
assertEquals("JPA in 5 steps -- updated", courseRepository.findById(10001L).getName());
// insert new course
Course course1 = courseRepository.save(new Course("JPA_JDBC"));
// check the value
assertEquals("JPA_JDBC", course1.getName());
}
}
JPQL – we use entities to make queries.
package com.brains.jpa.hibernate.jpahibernatedemo;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.brains.jpa.hibernate.jpahibernatedemo.entity.Course;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
@SpringBootTest(classes = JpaHibernateDemoApplication.class)
class JPQLTest {
@Autowired
EntityManager em;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
void jpql_basic() {
Query query = em.createQuery("select c from Course c");
List resultList = query.getResultList();
logger.info("list: -> {}", resultList);
}
// List of fixed type
@Test
void jpql_typed() {
TypedQuery query = em.createQuery("select c from Course c", Course.class);
List resultList = query.getResultList();
logger.info("Course: -> {}", resultList);
}
// Query with where clause
@Test
void jpql_where() {
TypedQuery query = em.createQuery("select c from Course c where name like '%10%'", Course.class);
List resultList = query.getResultList();
logger.info("Where Course: -> {}", resultList);
}
}
Leave a Reply