Showing posts with label native query. Show all posts
Showing posts with label native query. Show all posts

Saturday, 24 April 2021

Spring jpa: Project specific columns using native query

Step 1: Define entity class.

 

Employee.java

@Entity
@Table(name = "my_employee")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;

	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;

	@Column(name = "age")
	private int age;

	@Column(name = "salary")
	private double salary;

	......
	......
}

 

Step 2: Define IEmployee interface with the getter methods that you are interested to extract.

public interface IEmployee {

	int getId();

	String getFirst_name();

	String getLast_name();

}

Below table summarizes the column name and respective native getter method names.

 

Column Name

Method name

id

getId()

first_name

getFirst_name()

last_name

getLast_name()

Step 3: Write a query method to project the result to IEmployee interface.

@Query(value = "select id, first_name,last_name from my_employee", nativeQuery = true)
List<IEmployee> findAllEmpsViaNativeQuery();


As you see the declaration of ‘findAllEmpsViaNativeQuery’ method, the return type is IEmployee interface.

 

Find the below working application.

 

Step 1: Create new maven project ‘raw-sql-projection-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

<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>
	<groupId>com.sample.app</groupId>
	<artifactId>raw-sql-projection-demo</artifactId>
	<version>1</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>


	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>


		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
		</dependency>


	</dependencies>
</project>


Step 3: Create application.properties file under src/main/resources folder.

 

application.properties

logging.level.root=WARN
logging.level.org.hibernate=ERROR

## H2 specific properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2

spring.datasource.url=jdbc:h2:file:~/db/myOrg.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;

spring.datasource.username=krishna
spring.datasource.password=password123

spring.datasource.driverClassName=org.h2.Driver

## JPA specific properties
# Creates the schema, destroying previous data.
spring.jpa.hibernate.ddl-auto=create

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=false

## Database connection pooling properties
# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=3

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true


Step 4: Define Employee entity.

 

Employee.java

package com.sample.app.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "my_employee")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;

	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;

	@Column(name = "age")
	private int age;

	@Column(name = "salary")
	private double salary;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public static EmployeeBuilder builder() {
		return new EmployeeBuilder();
	}

	public static class EmployeeBuilder {
		private Employee emp;

		public EmployeeBuilder() {
			emp = new Employee();
		}

		public EmployeeBuilder firstName(String firstName) {
			emp.setFirstName(firstName);
			return this;
		}

		public EmployeeBuilder lastName(String lastName) {
			emp.setLastName(lastName);
			return this;
		}

		public EmployeeBuilder age(int age) {
			emp.setAge(age);
			return this;
		}

		public EmployeeBuilder salary(double salary) {
			emp.setSalary(salary);
			return this;
		}

		public Employee build() {
			return emp;
		}
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Employee [id=").append(id).append(", firstName=").append(firstName).append(", lastName=")
				.append(lastName).append(", age=").append(age).append(", salary=").append(salary).append("]");
		return builder.toString();
	}

}


Step 5: Define IEmployee interface to extract specific columns.

 

IEmployee.java

package com.sample.app.model;

public interface IEmployee {

	int getId();

	String getFirst_name();

	String getLast_name();

}


Step 6: Define EmployeeRepository interface.

 

EmployeeRepository.java

package com.sample.app.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.sample.app.entity.Employee;
import com.sample.app.model.IEmployee;

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

	@Query(value = "select id, first_name,last_name from my_employee", nativeQuery = true)
	List<IEmployee> findAllEmpsViaNativeQuery();

	@Query(value = "select id, first_name,last_name from my_employee where first_name=?1", nativeQuery = true)
	List<IEmployee> findAllEmpsByFirstNameViaNativeQuery(String firstName);

}


Step 7: Define main application class.

 

App.java

package com.sample.app;

import java.util.List;

import javax.transaction.Transactional;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.sample.app.entity.Employee;
import com.sample.app.model.IEmployee;
import com.sample.app.repository.EmployeeRepository;

@SpringBootApplication
public class App {

	public static void main(String args[]) {
		SpringApplication.run(App.class, args);
	}

	public void printEmployees(Iterable<Employee> emps, String msg) {
		System.out.println(msg);
		for (Employee emp : emps) {
			System.out.println(emp);
		}

		System.out.println();
	}

	public void printIEmployees(Iterable<IEmployee> emps, String msg) {
		System.out.println(msg);
		for (IEmployee emp : emps) {
			System.out.println(emp.getId() + " , " + emp.getFirst_name() + " , " + emp.getLast_name());
		}

		System.out.println();
	}

	@Bean
	@Transactional
	public CommandLineRunner demo(EmployeeRepository employeeRepository) {
		return (args) -> {
			Employee emp1 = Employee.builder().firstName("Ram").lastName("Gurram").age(32).salary(100000.23).build();
			Employee emp2 = Employee.builder().firstName("Ram").lastName("Chelli").age(43).salary(60000).build();
			Employee emp3 = Employee.builder().firstName("Gopi").lastName("Battu").age(45).salary(1000000).build();
			Employee emp4 = Employee.builder().firstName("Ram").lastName("Srikanth").age(39).salary(60000).build();
			Employee emp5 = Employee.builder().firstName("Surendra").lastName("Sami").age(32).salary(100000.23).build();
			Employee emp6 = Employee.builder().firstName("Deeraj").lastName("Arora").age(41).salary(1000000.23).build();
			Employee emp7 = Employee.builder().firstName("Sailu").lastName("Ptr").age(31).salary(50000.23).build();
			Employee emp8 = Employee.builder().firstName("Loopa").lastName("Battu").age(32).salary(80000.23).build();
			Employee emp9 = Employee.builder().firstName("Ram").lastName("Zlam").age(33).salary(80000.23).build();

			employeeRepository.save(emp1);
			employeeRepository.save(emp2);
			employeeRepository.save(emp3);
			employeeRepository.save(emp4);
			employeeRepository.save(emp5);
			employeeRepository.save(emp6);
			employeeRepository.save(emp7);
			employeeRepository.save(emp8);
			employeeRepository.save(emp9);

			List<Employee> emps = employeeRepository.findAll();
			printEmployees(emps, "All the employees information");

			List<IEmployee> iEmps = employeeRepository.findAllEmpsViaNativeQuery();
			printIEmployees(iEmps, "All the employees information using native query");

			iEmps = employeeRepository.findAllEmpsByFirstNameViaNativeQuery("Ram");
			printIEmployees(iEmps, "All the employees with firstName 'Ram'");

		};
	}

}

 

Total project structure looks like below.




Run App.java, you will see below messages in console.

All the employees information
Employee [id=1, firstName=Ram, lastName=Gurram, age=32, salary=100000.23]
Employee [id=2, firstName=Ram, lastName=Chelli, age=43, salary=60000.0]
Employee [id=3, firstName=Gopi, lastName=Battu, age=45, salary=1000000.0]
Employee [id=4, firstName=Ram, lastName=Srikanth, age=39, salary=60000.0]
Employee [id=5, firstName=Surendra, lastName=Sami, age=32, salary=100000.23]
Employee [id=6, firstName=Deeraj, lastName=Arora, age=41, salary=1000000.23]
Employee [id=7, firstName=Sailu, lastName=Ptr, age=31, salary=50000.23]
Employee [id=8, firstName=Loopa, lastName=Battu, age=32, salary=80000.23]
Employee [id=9, firstName=Ram, lastName=Zlam, age=33, salary=80000.23]

All the employees information using native query
1 , Ram , Gurram
2 , Ram , Chelli
3 , Gopi , Battu
4 , Ram , Srikanth
5 , Surendra , Sami
6 , Deeraj , Arora
7 , Sailu , Ptr
8 , Loopa , Battu
9 , Ram , Zlam

All the employees with firstName 'Ram'
1 , Ram , Gurram
2 , Ram , Chelli
4 , Ram , Srikanth
9 , Ram , Zlam


You can download complete working application from below link.

https://github.com/harikrishna553/springboot/tree/master/jpa/raw-sql-projection-demo









 

 

 

 

Previous                                                    Next                                                    Home

Wednesday, 18 September 2019

Spring data: Add custom functionality to a spring data repository


Sometimes the default queries and annotated queries may not satisfy our needs. In these case, we may need to add custom methods to the spring data repository. Spring Data allows to add custom data methods to the repository.

How can we add custom methods to a repository?
Step 1: Create an interface with custom methods.
public interface EmployeeCustomRepository {
         List<Employee> emps(List<Integer> empIds);
}

Step 2: Implement custom repository.
@Repository
public class EmployeeCustomRepositoryImpl implements EmployeeCustomRepository {

         @Override
         public List<Employee> emps(List<Integer> empIds) {
                  .....
                  .....
         }

}

Step 3: Make sure that the spring data repository extends the custom repository.

public interface EmployeeRepository extends JpaRepository<Employee, Integer>, EmployeeCustomRepository{

}

Find the below working application.

Employee.java
package com.sample.app.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employees")
public class Employee {
 
 @Id
 private int id;
 private String firstName;
 private String lastName;

 public Employee() {
 }

 public Employee(int id, String firstName, String lastName) {
  this.id = id;
  this.firstName = firstName;
  this.lastName = lastName;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
 }

}


EmployeeCustomRepository.java
package com.sample.app.repository;

import java.util.List;

import com.sample.app.entity.Employee;

public interface EmployeeCustomRepository {
 List<Employee> emps(List<Integer> empIds);
}


EmployeeCustomRepositoryImpl.java
package com.sample.app.repository.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import com.sample.app.entity.Employee;
import com.sample.app.repository.EmployeeCustomRepository;

@Repository
public class EmployeeCustomRepositoryImpl implements EmployeeCustomRepository {

 @PersistenceContext
 EntityManager entityManager;

 @SuppressWarnings("unchecked")
 @Override
 public List<Employee> emps(List<Integer> empIds) {

  Query query = entityManager.createNativeQuery("SELECT * FROM employees e WHERE e.id IN " + inQuery(empIds),
    Employee.class);

  return query.getResultList();
 }

 private static final String inQuery(List<Integer> empIds) {
  StringBuilder builder = new StringBuilder();

  builder.append("(");

  for (int id : empIds) {
   builder.append(id).append(",");
  }

  String str = builder.toString();

  String result = str.substring(0, str.length() - 1) + ")";
  return result;
 }

}


App.java
package com.sample.app;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.sample.app.entity.Employee;
import com.sample.app.repository.EmployeeRepository;

@SpringBootApplication
public class App {
 
 @Autowired
 EmployeeRepository empRepo;
 
 public static void main(String args[]) {
  SpringApplication.run(App.class, args);
 }

 @Bean
 public CommandLineRunner demo(EmployeeRepository employeeRepository) {
  return (args) -> {
   Employee emp1 = new Employee(1, "Lahari", "Gurram");
   Employee emp2 = new Employee(2, "bala", "Ponnam");
   Employee emp3 = new Employee(3, "Chandu", "Dondapati");
   Employee emp4 = new Employee(4, "Sudheer", "Ganji");
   Employee emp5 = new Employee(5, "Shankari", "Sri");
   
   empRepo.saveAll(Arrays.asList(emp1, emp2, emp3, emp4, emp5));
   
   empRepo.emps(Arrays.asList(2, 3, 5)).forEach(System.out::println);;
   
   
  };
 }
}


application.properties
logging.level.root=WARN
logging.level.org.hibernate=ERROR

## H2 specific properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2

spring.datasource.url=jdbc:h2:file:~/db/myOrg.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;

spring.datasource.username=krishna
spring.datasource.password=password123

spring.datasource.driverClassName=org.h2.Driver

## JPA specific properties
# Creates the schema, destroying previous data.
spring.jpa.hibernate.ddl-auto=create

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

## Database connection pooling properties
# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=10
spring.datasource.tomcat.max-idle=5
spring.datasource.tomcat.min-idle=3


pom.xml
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>springCRUDInMemory</groupId>
 <artifactId>springCRUDInMemory</artifactId>
 <version>1</version>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.6.RELEASE</version>
 </parent>

 <name>springbootApp</name>
 <url>http://maven.apache.org</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>

  <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
  <dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
  </dependency>

 </dependencies>
</project>


Total project structure looks like below.
Run App.java, you can see below messages in console.

Employee [id=2, firstName=bala, lastName=Ponnam]
Employee [id=3, firstName=Chandu, lastName=Dondapati]
Employee [id=5, firstName=Shankari, lastName=Sri]

You can download complete working application from this link.


Previous                                                    Next                                                    Home