1.Create springboot project using https://start.spring.io/
2.Add dependency , Spring Web, Mysql Driver, Spring JPA
3. Generate the code and , import as existing maven project
4.Since this is simple database sample add DBconnection details to the application.properties file
spring.datasource.url=jdbc:mysql://db_ip:3306/db_name?useSSL=false&serverTimezone=UTC
spring.datasource.username=user_name
spring.datasource.password=password
5.Next we create 3 layers virtually for easy understand and development
1.Control Layer
2.Service Layer
3.Repository Layer
6.Create Entity class for relevant table to be used,name City
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "cities_test") // Mapping table with DB
public class City {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private int population;
public City() {
}
public City(Long id, String name, int population) {
this.id = id;
this.name = name;
this.population = population;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
}
7.Extend CrudRepository and create CityRepository interface for doing db related transactions
Make sure to add @Repository annotation to the class
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CityRepository extends CrudRepository<City, Long>{
}
8.Then create and CityService interface for doing transaction with Repository
also add signature for retrieve data from db layer
import java.util.List;
import lk.inova.example.all_demo.repository.City;
public interface CityService {
List<City> findAllCities();
}
9.Then Create impl class by implementing above CityService interface method, also Autowired the CityRepository interface to service Impl class, make sure to set @Service annotation
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lk.inova.example.all_demo.repository.City;
import lk.inova.example.all_demo.repository.CityRepository;
import lk.inova.example.all_demo.service.CityService;
@Service
public class CityServiceImpl implements CityService {
@Autowired
CityRepository repository;
@Override
public List<City> findAllCities() {
return (List<City>) repository.findAll();
}
}
10.Then create class MyCityConroller for any transaction about cities - Get Cities, Update, Delete..etc
makesure to add annotation @RestController,...Also Add request mapping and GetMapping to relevant method. also Autowired CityServiceImple class.
@RestController
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lk.inova.example.all_demo.repository.City;
import lk.inova.example.all_demo.service.impl.CityServiceImpl;
@RestController
@RequestMapping("/db")
public class MyCityController {
@Autowired
CityServiceImpl cityServiceImpl;
@GetMapping("/cities")
public List<City> getAllCities(){
return cityServiceImpl.findAllCities();
}
}
11.Now you can see the all cities
http://localhost:8080/db/cities
note :
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>lk.inova.example</groupId>
<artifactId>all_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>all_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
How to handle Internal Server Error - 500 when relevant city id is not found(give 404):
ReplyDeleteNew Class :
package lk.inova.example.all_demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class CityNotFoundException extends RuntimeException {
public CityNotFoundException(String message){
super(message);
}
}
// If pass City Id is not found no city found and handle below
@Override
public String findCityName(long id) {
Optional city = repository.findById(id);
if (city == null || city.isEmpty()) {
throw new CityNotFoundException("id is: "+ id);
}
City c = city.get();
return city.get().getName();
}
//controller method
// check 404 and get correct name for id
@GetMapping("/city/{id}") // ?id=5
public String getCity404(@PathVariable long id){
String cityName = cityServiceImpl.findCityName(id);
return cityName;
}
// Calling URL -Rest API
http://localhost:8080/db/city/41
//Output
{
"timestamp": "2021-09-03T10:39:51.839+00:00",
"status": 404,
"error": "Not Found",
"path": "/db/city/41"
}
Retrieve Data Using Sql
ReplyDelete1.First create response class "CityListResponseDto.java" with mapping to the Query
package lk.inova.example.all_demo.repository.dao.wrapper;
import javax.persistence.SqlResultSetMapping;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@SqlResultSetMapping(name = "CityListResponseDtoMapping", entities = {
@EntityResult(entityClass = CityListResponseDto.class, fields = {
@FieldResult(name = "name", column = "name_q"),
@FieldResult(name = "population", column = "population_q"),
@FieldResult(name = "id", column = "id_q"),
}),
})
@Data
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class CityListResponseDto {
@Id
@JsonProperty(value = "id")
private Long id;
@JsonProperty(value = "name")
private String name;
@JsonProperty(value = "population")
private Integer population;
}
2.Write Sql for retrieve data "CityDaoImpl.java" which is implementing the interface "CityDao.java"
Interface
package lk.inova.example.all_demo.repository.dao;
import java.util.List;
import lk.inova.example.all_demo.repository.dao.wrapper.CityListResponseDto;
public interface CityDao {
List getCityList(Long id);
}
---implementation java class
package lk.inova.example.all_demo.repository.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import lk.inova.example.all_demo.repository.dao.wrapper.CityListResponseDto;
@Repository
public class CityDaoImpl implements CityDao{
@PersistenceContext
private EntityManager entityManager;
@Override
public List getCityList(Long id) {
StringBuilder nativeQuery = new StringBuilder();
nativeQuery.append("SELECT ");
nativeQuery.append("name as name_q, ");
nativeQuery.append("population AS population_q, ");
nativeQuery.append("id AS id_q ");
nativeQuery.append("FROM cities_test ");
nativeQuery.append("WHERE id = :id ");
try {
Query query = this.entityManager.createNativeQuery(nativeQuery.toString(), "CityListResponseDtoMapping")
.setParameter("id", id);
// ;
return query.getResultList();
}catch(Exception e) {
System.out.println("ERROR "+ e.getMessage() );
e.printStackTrace() ;
return null;
}
}
}
3.Add method to Service interface
List getCityList(long id);// using query
4.Add implementation method to serviceImpl
@Override
public List getCityList(long id) {
// TODO Auto-generated method stub
return cityDaoImpl.getCityList(id);
}
5.Controller method for retrieve data
@GetMapping("/city_q/{id}") // ?id=a
public List getCityListByQuery(@PathVariable long id){
return cityServiceImpl.getCityList(id);
}
output
URL
http://localhost:8080/db/city_q/5
results
0
id 5
name "Los Angeles"
population 3971000
Added below POM entry for above Data retrieve using Sql Example
ReplyDeleteorg.projectlombok
lombok
true
As the above example we can pass object as request instead of the id
ReplyDeletepackage lk.inova.example.all_demo.common;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CityRequestDto implements Serializable {/**
*
*/
private static final long serialVersionUID = 1L;
@JsonProperty("id")
@NotNull(message = "value cannot be null")
@ApiModelProperty(required = true, value = "required field")
private Long id;
@JsonProperty("name")
@NotNull(message = "value cannot be null")
@ApiModelProperty(required = true, value = "required field")
private String name;
}
then controller method set as POST Mapping and as below
@PostMapping("/city_p")
public List getCityListByQuery(CityRequestDto cityRequestDto){
return cityServiceImpl.getCityList(cityRequestDto);
}