Step 1: Add JPA and H2 Dependencies
In your pom.xml, add the following dependencies for Spring Data JPA and the H2 in-memory database:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Step 2: Configure Spring Boot Application Properties
In src/main/resources/application.properties:
# Enable SQL query logging spring.jpa.show-sql=true # Enable H2 console spring.h2.console.enabled=true spring.h2.console.path=/h2-console
Step 3: Create the JPA Entity
Create Item.java in the appropriate package. This entity will map to the database table.
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Transient;
@Entity
public class Item {
@Id
private int id;
private String name;
private int price;
private int quantity;
@Transient
private int value; // Not stored in the DB, used for business logic.
// Default constructor needed by JPA
protected Item() {}
public Item(int id, String name, int price, int quantity) {
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
}
// Getters and setters omitted for brevity (generate them)
}
Step 4: Create the Repository Interface
Create an interface extending JpaRepository:
import org.springframework.data.jpa.repository.JpaRepository;
public interface ItemRepository extends JpaRepository<Item, Integer> {
// No methods needed; JpaRepository provides CRUD operations.
}
Step 5: Create the Business Service
An example service to retrieve all items and add business logic (calculating value = price * quantity):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ItemBusinessService {
@Autowired
private ItemRepository repository;
public List<Item> retrieveAllItems() {
List<Item> items = repository.findAll();
for (Item item : items) {
item.setValue(item.getPrice() * item.getQuantity());
}
return items;
}
}
Step 6: Create the REST Controller
Expose the business service through a controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ItemController {
@Autowired
private ItemBusinessService businessService;
@GetMapping("/all-items-from-database")
public List<Item> retrieveAllItems() {
return businessService.retrieveAllItems();
}
}
Step 7: Unit Testing the Controller
Since controller depends on the business service, mock the business service and test controller JSON response using Spring Boot test utilities.
Example with Mockito and MockMvc (in ItemControllerTest.java):
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(ItemController.class)
public class ItemControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ItemBusinessService businessService;
@Test
public void testRetrieveAllItems() throws Exception {
List<Item> items = Arrays.asList(
new Item(10001, "item1", 10, 20),
new Item(10002, "item2", 5, 10)
);
// Mock the business service
Mockito.when(businessService.retrieveAllItems()).thenReturn(items);
mockMvc.perform(get("/all-items-from-database"))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].name").value("item1"))
.andExpect(jsonPath("$[1].name").value("item2"));
}
}
Step 7: Unit Testing the Business Service
Mock the repository and test business logic:
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
public class ItemBusinessServiceTest {
@Mock
private ItemRepository repository;
@InjectMocks
private ItemBusinessService businessService;
public ItemBusinessServiceTest() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testRetrieveAllItems() {
List<Item> items = Arrays.asList(
new Item(10001, "item1", 10, 10), // expected value = 100
new Item(10002, "item2", 20, 20) // expected value = 400
);
when(repository.findAll()).thenReturn(items);
List<Item> result = businessService.retrieveAllItems();
assertEquals(100, result.get(0).getValue());
assertEquals(400, result.get(1).getValue());
}
}
