Spring JDBC or DAO
Spring JDBC or DAO
INDEX
Spring JDBC/ DAO ---------------------------------------------------------
1. Introduction 04
2. JdbcTemplate 08
3. Callback Interface 27
a. RowMapper<T> 28
b. ResultSetExtractor<T> 37
c. RowCallbackHandler 41
4. NamedParameterJdbcTemplate 44
5. SimpleJdbclnsert or Call 53
a. SimpleJdbclnsert 53
b. SimpleJdbcCall 59
6. Mapping SQL Operations as Sub classes 64
7. Working with properties file and yml/ yaml files in Spring/ Spring Boot
75
a. YML/ YAML 81
8. Profiles in Spring or Spring Boot 89
9. Spring Boot Flow for Standalone application 121
Note:
✓ Common logics these are same in all JDBC apps (boilerplate code),
Application specific logics will change based on the Db s/w we use.
✓ The code that repeats across the multiple parts of Project /application
either with no changes or with minor changes is called boilerplate code.
Persistence: The process of saving and managing data for long time is called
persistence.
Persistence store: The place where persistence takes place.
e.g. files, DB s/w (Best)
Persistence operations: insert, update, delete, select operations are called
persistence operations, these are also called CURD/ CRUD operations
C -> create, U -> update, R -> Read, D->Delete
Persistence logic: The logic to perform curd operations
e.g. JDBC code, Iostreams code, hibernate code, Spring JDBC code and
etc.
IO Streams:
• For small apps, small data like files.
• e.g. Desktop games, mobile games.
Plain JDBC and Spring JDBC:
• Large scale Apps getting huge amount data batch by batch for
processing having DB s/w as persistence store.
Note:
✓ Spring Data module is having capability of generating 100% Basic CURD
operations code dynamically for the given DB tables.
✓ Spring JDBC internally uses plain JDBC and just simplifies JDBC style
persistence logic i.e. (70% Spring JDBC will take care and 30% should be
taken care by programmer).
✓ Spring ORM internally uses plain ORM and just simplifies ORM style
objects-based persistence logic i.e. (70% Spring ORM will take care and
30% should be taken care by programmer)
Note: The direct sub classes of java.lang.Exception class are called Checked
Exception and The direct sub classes of java.lang.RuntimeException class
are called Unchecked Exception.
Note: Spring JDBC Persistence logic is still DB s/w dependent Persistence logic
because its SQL queries-based Persistence logic.
JdbcTemplate
It is central class/ API class for entire Spring JDBC i.e. remaining
approaches of Spring JDBC programming internally uses this
JdbcTemplate.
Designed based on Template method design pattern which says define
an algorithm to complete a task where common aspects will be taken
care by Spring JDBC and lets the programmer to take care of only
specific activities.
Need DataSource obj as Dependent object.
Gives query(-) and queryForXxx(-) for select query execution and gives
update(-) method for non-select query execution.
JdbcTemplate supports only Positional params.
JdbcTemplate Example:
persistence-beans.xml
<beans>
<bean id="hkDs" class="pgk.HikariDataSource">
............
</bean>
applicationContext.xml
<import resource="persistence-beans.xml"/>
<import resource="service-beans.xml"/>
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
</dependencies>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/bea
ns http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="persistence-beans.xml"/>
<import resource="service-beans.xml"/>
</beans>
service-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/bea
ns http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Service configuration -->
<bean id="empService"
class="com.nt.service.EmployeeMgmtService">
<constructor-arg ref="empDAO"/>
</bean> </beans>
EmployeeDAOImpl.java
package com.nt.dao;
import org.springframework.jdbc.core.JdbcTemplate;
public class EmployeeDAOImpl implements IEmployeeDAO {
private static final String GET_EMPLOYEES_COUNT = "SELECT
COUNT(*) FROM EMP";
private JdbcTemplate jt;
public EmployeeDAOImpl(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public int getEmployeeCount() {
int count = 0;
count = jt.queryForObject(GET_EMPLOYEES_COUNT,
Integer.class);
return count;
}
}
IEmployeeMgmtService.java
package com.nt.service;
public interface IEmployeeMgmtService {
public int fetchEmpsCount();
}
EmployeeMgmtServiceImpl.java
package com.nt.service;
import com.nt.dao.IEmployeeDAO;
@Override
public Map<String, Object> getEmployeeDetailsByNo(int eno) {
Map<String, Object> map = null;
map = jt.queryForMap(“SELECT ENPNO, ENAME, JOB, SAL,
DEPTNO FROM EMP WHERE EMPNO=?”, eno);
return map;
}
@Override
public List<Map<String, Object>> getEmployeesDetailsByDesg(String
desg1, String desg2) {
return jt.queryForList(“SELECT EMPNO, ENAME, SAL, JOB,
DEPTNO FROM EMP WHERE JOB IN (?, ?) ORDER BY JOB”,
desg1, desg2);
}
16 Prepared By - Nirmala Kumar Sahu
IEmployeeDAO.java
public String getEmployeeNameByNo(int eno);
public Map<String, Object> getEmployeeDetailsByNo(int eno);
public List<Map<String, Object>> getEmployeesDetailsByDesg(String
desg1, String desg2);
public int insert(String name, String desg, float sal);
public int addBonusToEmployeeByDesg(String desg, float bonus);
EmployeeDAOImpl.java
private static final String GET_EMPLOYEE_NAME_BY_ID = "SELECT ENAME
FROM EMP WHERE EMPNO=?";
private static final String GET_EMPLOYEE_DETAILS_BY_ID = "SELECT
EMPNO, ENAME, SAL, JOB, DEPTNO FROM EMP WHERE EMPNO=?";
private static final String GET_EMPLOYEES_DETAILS_BY_JOB =
"SELECT EMPNO, ENAME, SAL, JOB, DEPTNO FROM EMP WHERE JOB IN (?,
?) ORDER BY JOB";
private static final String INSERT_EMPLOYEE = "INSERT INTO EMP
(EMPNO, ENAME, JOB, SAL) VALUES (ENO_SEQ.NEXTVAL, ?, ?, ?)";
private static final String ADD_BONUS_BY_JOB = "UPDATE EMP SET
SAL=SAL+? WHERE JOB=?";
@Override
public String getEmployeeNameByNo(int eno) {
String name = null;
name = jt.queryForObject(GET_EMPLOYEE_NAME_BY_ID,
String.class, eno);
return name;
}
@Override
public Map<String, Object> getEmployeeDetailsByNo(int eno) {
Map<String, Object> map = null;
map = jt.queryForMap(GET_EMPLOYEE_DETAILS_BY_ID, eno);
return map; 17 Prepared By - Nirmala Kumar Sahu
}
map = jt.queryForMap(GET_EMPLOYEE_DETAILS_BY_ID, eno);
return map;
}
@Override
public List<Map<String, Object>> getEmployeesDetailsByDesg(String
desg1, String desg2) {
return jt.queryForList(GET_EMPLOYEES_DETAILS_BY_JOB,
desg1, desg2);
}
@Override
public int insert(String name, String desg, float sal) {
return jt.update(INSERT_EMPLOYEE, name, desg, sal);
}
@Override
public int addBonusToEmployeeByDesg(String desg, float bonus) {
return jt.update(ADD_BONUS_BY_JOB, bonus, desg);
}
IEmployeeMgmtService.java
public String fetchEmployeeNameByNo(int eno);
public Map<String, Object> fetchEmployeeDetailsByNo(int eno);
public List<Map<String, Object>>
fetchEmployeesDetailsByDesg(String desg1, String desg2);
public String resgisteEmployee(String name, String desg, float sal);
public String putBonusToEmployeeByDesg(String desg, float bonus);
EmployeeMgmtServiceImpl.java
@Override
public String fetchEmployeeNameByNo(int eno) {
return dao.getEmployeeNameByNo(eno);
}
@Override
public Map<String, Object> fetchEmployeeDetailsByNo(int eno) {
return dao.getEmployeeDetailsByNo(eno);
}
@Override
18 Prepared By - Nirmala Kumar Sahu
public List<Map<String, Object>>
fetchEmployeesDetailsByDesg(String desg1, String desg2) {
return dao.getEmployeesDetailsByDesg(desg1, desg2);
@Override
public List<Map<String, Object>>
fetchEmployeesDetailsByDesg(String desg1, String desg2) {
return dao.getEmployeesDetailsByDesg(desg1, desg2);
}
@Override
public String resgisteEmployee(String name, String desg, float sal) {
int count = 0;
//use dao
count = dao.insert(name, desg, sal);
return count==0?"Employee is not registered":"Employee is
registered";
}
@Override
public String putBonusToEmployeeByDesg(String desg, float bonus) {
int count = 0;
//use dao
count = dao.addBonusToEmployeeByDesg(desg, bonus);
return count==0?desg+" Employee record found for add
bouns":count+" No. of records are added with bouns";
}
JdbcTemplateTest.java
System.out.println("--------------------------");
try {
System.out.println("7499 Employee Name is :
"+service.fetchEmployeeNameByNo(7499));
} catch (DataAccessException dae) {
dae.printStackTrace();
}
System.out.println("--------------------------");
try {
System.out.println("7499 Employee Name is :
"+service.fetchEmployeeDetailsByNo(7499));
} catch (DataAccessException dae) {
dae.printStackTrace();
}
System.out.println("--------------------------");
try {
19
//System.out.println("CLERK, Prepared ByEmployee
MANAGER - Nirmala Kumar Sahu
Details : "+service.fetchEmployeesDetailsByDesg("CLERK", "MANAGER"));
service.fetchEmployeesDetailsByDesg("CLERK",
try {
//System.out.println("CLERK, MANAGER Employee
Details : "+service.fetchEmployeesDetailsByDesg("CLERK", "MANAGER"));
service.fetchEmployeesDetailsByDesg("CLERK",
"MANAGER").forEach(System.out::println);
EmployeeMgmtServiceImpl.java
@Service("empService")
public class EmployeeMgmtService implements IEmployeeMgmtService {
@Autowired
private IEmployeeDAO dao;
service-beans.xml
<context:component-scan base-package="com.nt.service"/>
persistence-beans.xml
<!-- HikariCP DS configuration -->
<bean id="hkDs" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="jdbcUrl"
value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="username" value="system"/>
<property name="password" value="manager"/>
<property name="minimumIdle" value="10"/>
<property name="maximumPoolSize" value="30"/>
</bean>
<context:component-scan base-package="com.nt.dao"/>
• Add the following code in their respective files and change the
container in Test class.
jdbc.properties
#jdbc properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.user=system
jdbc.pwd=manager
jdbc.hcp.minisize=10
jdbc.hcp.maxsize=100
AppConfig.java
package com.nt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({PersistenceConfig.class, ServiceConfig.class})
public class AppConfig {
}
PersistenceConfig.java
package com.nt.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
@ComponentScan(basePackages = "com.nt.dao")
@PropertySource("com/nt/commons/jdbc.properties")
public class PersistenceConfig {
@Autowired
private Environment env;
@Bean(name="hkDs")
public HikariDataSource createDataSource() {
HikariDataSource hkDs = null;
hkDs = new HikariDataSource();
hkDs.setDriverClassName(env.getRequiredProperty("jdbc.driver"));
hkDs.setJdbcUrl(env.getRequiredProperty("jdbc.url"));
hkDs.setUsername(env.getRequiredProperty("jdbc.user"));
hkDs.setPassword(env.getRequiredProperty("jdbc.pwd"));
hkDs.setMinimumIdle(Integer.parseInt(env.getRequiredProperty("jdb
c.hcp.minisize")));
hkDs.setMaximumPoolSize(Integer.parseInt(env.getRequiredProperty
23 Prepared By - Nirmala Kumar Sahu
("jdbc.hcp.maxsize")));
return hkDs;
hkDs.setMaximumPoolSize(Integer.parseInt(env.getRequiredProperty
("jdbc.hcp.maxsize")));
return hkDs;
}
@Bean(name="jt")
public JdbcTemplate createJT() {
return new JdbcTemplate(createDataSource());
}
}
DaoBootProj01JdbcTemplateDirectMethodApplication.java
package com.nt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import com.nt.service.IEmployeeMgmtService;
@SpringBootApplication
public class DaoBootProj01JdbcTemplateDirectMethodsApplication {
b. No ability to use our choice JDBC statement objects to send and execute
SQL queries in DB s/w.
c. Customization of Results (SQL Query results) is more required.
Callback Interface
Callback method:
The method that executes automatically is called Callback method i.e.
this method will be called by underlying environment like Spring JDBC or
Container or F/w or server automatically.
Servlet life cycle methods are called Container callback methods because
Callback Interface:
The interface that contains the declaration of callback methods is called
Callback Interface.
Spring JDBC is providing multiple callback Interfaces, they are
a. RowMapper: Gives RS object to customize single record/ row (like
BO)
b. ResultSetExtractor: Gives RS object to customize multiple records
(like ListBO) -> stateless
c. RowCallbackHandler: Gives RS object to customize multiple
records (like ListBO)-> stateful
d. PreparedStatementCreator: Gives JDBC connection object to
create PreparedStatement object
e. PreparedStatementSetter: Gives JDBC PreparedStatement object
to set values to query params and to execute Query
f. StatementCallback
g. PreparedStatementCallback
h. CallbableStatementCallback
i. PreparedStatementBatchSetter
and etc.
RowMapper<T>
• callback method is
public <T> mapRow (ResultSet rs, int index)
• Very useful to convert RS object single record to BO class object.
• queryForObject (-, -, -) is having overloaded forms having RowMapper as
the parameter type.
DBScript.txt
CREATE TABLE "SYSTEM"."STUDENT"
("SNO" NUMBER(*,0) NOT NULL ENABLE,
"SNAME" VARCHAR2(20 BYTE),
"ADDRESS" VARCHAR2(20 BYTE),
"AVG" FLOAT(126),
CONSTRAINT "STUDENT_PK" PRIMARY KEY ("SNO"));
IStudentDAO.java
package com.nt.dao;
import com.nt.bo.StudentBO;
public interface IStudentDAO {
public StudentBO getStudentByNo(int sno);
}
StudentDAOImpl.java
package com.nt.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
31 Prepared By - Nirmala Kumar Sahu
import com.nt.bo.StudentBO;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.nt.bo.StudentBO;
@Repository("studDAO")
public class StudentDAOImpl implements IStudentDAO {
private static final String GET_STUDENT_BY_ID = "SELECT SNO,
SNAME, ADDRESS, AVG FROM STUDENT WHERE SNO=?";
@Autowired
private JdbcTemplate jt;
@Override
public StudentBO getStudentByNo(int sno) {
return jt.queryForObject(GET_STUDENT_BY_ID, new
StudentMapper(), sno);
}
//Nested inner class
private static class StudentMapper implements
RowMapper<StudentBO> {
@Override
public StudentBO mapRow(ResultSet rs, int rowNum) throws
SQLException {
StudentBO bo = null;
//convert RS record into student BO class object
bo = new StudentBO();
bo.setSno(rs.getInt(1));
bo.setSname(rs.getString(2));
bo.setAddress(rs.getString(3));
bo.setAvg(rs.getFloat(4));
return bo;
}
}
}
IStudentMgmtService.java
package com.nt.service;
import com.nt.dto.StudentDTO;
public interface IStudentMgmtService {
public StudentDTO fetchStudentById(int sno);
}
StudentBO.java
package com.nt.bo;
import lombok.Data;
@Data
public class StudentBO {
private int sno;
private String sname;
private String address;
private float avg;
}
RowMapperTest.java
package com.nt.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import com.nt.dto.StudentDTO;
import com.nt.service.IStudentMgmtService;
public class RowMapperTest {
public static void main(String[] args) {
ApplicationContext ctx = null;
IStudentMgmtService service = null;
StudentDTO dto = null;
// Create Container
ctx = new
ClassPathXmlApplicationContext("com/nt/cfgs/applicationContext.xml");
//get Service class object
service = ctx.getBean("studService",
IStudentMgmtService.class);
//invoke method
try {
dto = service.fetchStudentById(101);
System.out.println(dto);
34 Prepared By - Nirmala Kumar Sahu
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
dto = service.fetchStudentById(101);
System.out.println(dto);
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
System.err.println("Record not found");
else if (dae instanceof BadSqlGrammarException)
System.err.println("SQL syntax problem");
else
System.err.println("other internal probelm");
dae.printStackTrace();
}
((AbstractApplicationContext) ctx).close();
}
}
Lambda Expression based Anonymous inner class logic while working with
queryForObject (-, -, -) having RowMapper:
@Override
public StudentBO getStudentByNo(int sno) {
return jt.queryForObject(GET_STUDENT_BY_ID, (rs, rowNum) -
>{
StudentBO bo = null;
//convert RS record into student BO class object
bo = new StudentBO();
bo.setSno(rs.getInt(1));
bo.setSname(rs.getString(2));
bo.setAddress(rs.getString(3));
bo.setAvg(rs.getFloat(4));
return bo;
}, sno);
}
@Override
public StudentBO getStudentByNo(int sno) {
return jt.queryForObject(GET_STUDENT_BY_ID, new
BeanPropertyRowMapper<>(StudentBO.class), sno);
}
ResultSetExtractor<T>
If SELECT SQL Query execution gives multiple records to process then go
for ResultSetExtractor<T> or RowCallbackHandler<T>.
The Best use case is getting List of BO class objects from RS after
executing Select SQL query that gives multiple records.
StudentDAOImpl.java
private static final String GET_STUDENTS_BY_CITIES = "SELECT SNO,
SNAME, ADDRESS, AVG FROM STUDENT WHERE ADDRESS IN(?, ?, ?)";
\\\\ @Override
public List<StudentBO> getStudentsByCities(String city1, String city2,
String city3) {
return jt.query(GET_STUDENTS_BY_CITIES, new
StudentExtractor(), city1, city2, city3);
}
private static class StudentExtractor implements
ResultSetExtractor<List<StudentBO>>{
@Override
public List<StudentBO> extractData(ResultSet rs) throws
SQLException, DataAccessException {
List<StudentBO> listBO = new ArrayList<>();
//copy Rs object records to listBO
while (rs.next()) {
StudentBO bo = new StudentBO();
bo.setSno(rs.getInt(1));
bo.setSname(rs.getString(2));
bo.setAddress(rs.getString(3));
bo.setAvg(rs.getFloat(4));
listBO.add(bo);
}
return listBO;
}
}
38 Prepared By - Nirmala Kumar Sahu
IStudentMgmtService.java
public List<StudentDTO> fetchStudentsByCities(String city1,String
city2, String city3);
StudentMgmtServiceImpl.java
@Override
public List<StudentDTO> fetchStudentsByCities(String city1, String
city2, String city3) {
List<StudentBO> listBO = null;
//use DAO
listBO = dao.getStudentsByCities(city1, city2, city3);
//copy listBO to list DTO
List<StudentDTO> listDTO = new ArrayList<>();
listBO.forEach(bo->{
StudentDTO dto = new StudentDTO();
BeanUtils.copyProperties(bo, dto);
listDTO.add(dto);
});
return listDTO;
}
RowMapperTest.java
try {
List<StudentDTO> listDTO =
service.fetchStudentsByCities("hyd", "vizg", "delhi");
listDTO.forEach(System.out::println);
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
System.err.println("Record not found");
else if (dae instanceof BadSqlGrammarException)
System.err.println("SQL syntax problem");
else
System.err.println("other internal probelm");
dae.printStackTrace();
}
RowCallbackHandler
Method is: public void processRow (ResultSet rs) throws SQLException
It is stateful be implementation class obj remembers: the state across
the multiple executions of processRow (-) method.
@Override
public void processRow(ResultSet rs) throws
SQLException {
//convert RS record into BO
StudentBO bo = new StudentBO();
bo.setSno(rs.getInt(1));
bo.setSname(rs.getString(2));
bo.setAddress(rs.getString(3));
bo.setAvg(rs.getFloat(4));
listBO.add(bo);
}
}, city1, city2, city3);
return listBO;
}
NamedParameterJdbcTemplate
It is given to support named parameters in the SQL query.
The Limitation with positional params (?) is providing index and setting
values to those parameters according to the index is bit complex
especially if the query having multiple positional parameters.
To overcome the above problem use named parameters (:<name>)
which gives name to each parameter and we can set values to
parameters by specifying their name.
Note:
✓ JdbcTemplate does not support Named Parameters. It supports only
Positional parameters.
✓ NamedParameterJdbcTemplate supports named Parameters but does
not support positional parameters.
• Develop the above directory structure using maven setup and package,
class, XML file and add the jar dependencies to pom.xml, then use the
following code with in their respective file.
• Change to Java 1.8 or its higher version.
• Rest of code copy from DAOAnnoProj01-JdbcTemplate-DirectMethods.
persistence-beans.xml
<!-- JdbcTemplate configuration -->
<bean id="template"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcT
emplate">
<constructor-arg ref="hkDs"/>
</bean>
46 Prepared By - Nirmala Kumar Sahu
EmployeeBO.java
package com.nt.bo;
import lombok.Data;
@Data
public class EmployeeBO {
private Integer empno;
private String ename;
private String job;
private Float sal;
}
EmployeeDTO.java
package com.nt.dto;
import lombok.Data;
@Data
public class EmployeeDTO {
private Integer empno;
private String ename;
private String job;
private Float sal;
}
IEmployeeDAO.java
package com.nt.dao;
import java.util.List;
import com.nt.bo.EmployeeBO;
EmployeeMgmtServiceImpl.java
package com.nt.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.nt.bo.EmployeeBO;
import com.nt.dao.IEmployeeDAO;
import com.nt.dto.EmployeeDTO;
@Service("empService")
public class EmployeeMgmtServiceImpl implements
IEmployeeMgmtService {
@Autowired
private IEmployeeDAO dao;
@Override
public String fetchEmployeeNameByNo(int no) {
return dao.getEmployeeNameByNo(no);
}
@Override
public List<EmployeeDTO> fetchEmployeeDetailsByDesgs(String
desg1, String desg2, String desg3) {
//use DAO
List<EmployeeBO> listBO =
dao.getEmployeeDetailsByDesgs(desg1, desg2, desg3);
//copy listBO to listDTO
List<EmployeeDTO> listDTO = new ArrayList<>();
listBO.forEach(bo->{
EmployeeDTO dto = new EmployeeDTO();
BeanUtils.copyProperties(bo, dto);
listDTO.add(dto);50 Prepared By - Nirmala Kumar Sahu
});
return listDTO;
}
BeanUtils.copyProperties(bo, dto);
listDTO.add(dto);
});
return listDTO;
}
@Override
public String registerEmployee(EmployeeDTO dto) {
//Convert DTO to BO
EmployeeBO bo = new EmployeeBO();
BeanUtils.copyProperties(dto, bo);
//use DAO
int count = dao.insertEmployee(bo);
return count==1?"Employee Registered":"Employee not
Registered";
}
}
NamedParameterJdbcTemplateTest.java
package com.nt.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import com.nt.dto.EmployeeDTO;
import com.nt.service.IEmployeeMgmtService;
public class NamedParameterJdbcTemplateTest {
public static void main(String[] args) {
ApplicationContext ctx = null;
IEmployeeMgmtService service = null;
// Create IoC container
ctx = new
ClassPathXmlApplicationContext("com/nt/cfgs/applicationContext.xml");
// get Service class object
service = ctx.getBean("empService",
IEmployeeMgmtService.class);
// invoke method 51 Prepared By - Nirmala Kumar Sahu
try {
System.out.println("Employee Name :
IEmployeeMgmtService.class);
// invoke method
try {
System.out.println("Employee Name :
"+service.fetchEmployeeNameByNo(7900));
System.out.println("-----------------");
service.fetchEmployeeDetailsByDesgs("MANAGER",
"CLERK", "SALESMAN").forEach(System.out::println);
System.out.println("------------------------");
EmployeeDTO dto = new EmployeeDTO();
dto.setEmpno(3534);
dto.setEname("RAJESH");
dto.setJob("SALESMAN");
dto.setSal(45456.6f);
System.out.println(service.registerEmployee(dto));
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
System.err.println("Record not found");
else if (dae instanceof BadSqlGrammarException)
System.err.println("SQL syntax problem");
else
System.err.println("other internal probelm");
dae.printStackTrace();
}
((AbstractApplicationContext) ctx).close();
}
}
SimpleJdbcTemplate:
lntroduced in spring 2.x as alternate to JdbcTemplate supporting new
features of that time like generics, var args and etc.
Continued and deprecated in spring 3.x because they upgraded
JdbcTemplate itself supporting features like generics, var args and etc.
In Spring 4.1, the SimpleJdbcTemplate is removed.
SimpleJdbclnsert
|--> DS (as dependent obj)
|--> setTable (-)
|--> int execute (Map<String, Object> map)
takes column names and column values.
(or)
|--> int execute (SqlParameterSource source)
|--> MapSqlParameterSource (c)
using addValue (-, -) we need to pass column
names and column values
|--> BeanPropertySqlParameterSource(c)
Here we can pass JavaBean object as input for
column names and column values but DB table
column names and Java Bean property names
must match.
persistence-beans.xml
<!-- SimpleJdbcInsert configuration -->
<bean id="sji"
class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
<constructor-arg ref="hkDs"/>
</bean>
BankAccountBO.java
package com.nt.bo;
import lombok.Data;
@Data
public class BankAccountBO {
private Long accno;
private String holderName;
private Float balance;
private String status;
}
BankAccountDTO.java
package com.nt.dto;
import lombok.Data;
@Data
public class BankAccountDTO {
private Long accno;
private String holderName;
private Float balance;
private String status;
}
BankAccountDAOImpl.java
package com.nt.dao;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import com.nt.bo.BankAccountBO;
@Repository("accDAO")
public class BankAccountDAOImpl implements IBankAccountDAO {
@Autowired
private SimpleJdbcInsert sji;
@Override
public int register(BankAccountBO bo) {
//prepare Map object having columns and values
Map<String, Object> map = Map.of("accno", bo.getAccno(),
"holderName", bo.getHolderName(), "balance", bo.getBalance(), "status",
bo.getStatus());
//set db table name
sji.setTableName("BANK_ACCOUNT");
//execute query by generating the query dynamically
int count = sji.execute(map);
return count;
}
BankAccountMgmtServiceImpl.java
package com.nt.service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.nt.bo.BankAccountBO;
import com.nt.dao.IBankAccountDAO;
import com.nt.dto.BankAccountDTO;
@Service("accService")
public class BankAccountServiceImpl implements IBankAccountService {
@Autowired
private IBankAccountDAO dao;
@Override
public String createBankAccount(BankAccountDTO dto) {
BankAccountBO bo = new BankAccountBO();
//convert DTO to BO
BeanUtils.copyProperties(dto, bo);
//use dao
int count = dao.register(bo);
return count==1?dto.getHolderName()+" your acccount has
created":dto.getHolderName()+" your acccount has not created yet";
}
}
SimpleJdbcInsertTest.java
package com.nt.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import
57 Prepared By - Nirmala Kumar Sahu
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import com.nt.dto.BankAccountDTO;
import com.nt.service.IBankAccountService;
public class SimpleJdbcInsertTest {
public static void main(String[] args) {
ApplicationContext ctx = null;
IBankAccountService service = null;
// Create IoC container
ctx = new
ClassPathXmlApplicationContext("com/nt/cfgs/applicationContext.xml");
// get Service class object
service = ctx.getBean("accService", IBankAccountService.class);
// invoke method
try {
BankAccountDTO dto = new BankAccountDTO();
dto.setAccno(6489724l); dto.setHolderName("Ramesh");
dto.setBalance(347374f); dto.setStatus("Active");
System.out.println(service.createBankAccount(dto));
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
System.err.println("Record not found");
else if (dae instanceof BadSqlGrammarException)
System.err.println("SQL syntax problem");
else
System.err.println("other internal probelm");
dae.printStackTrace();
}
((AbstractApplicationContext) ctx).close();
}
}
BankAccountDAOImpl.java
@Override
public int register(BankAccountBO bo) {
//prepare BeanPropertySqlParameterSource object having BO
object
//Here column names must match to BO class property name.
BeanPropertySqlParameterSource bpsps = new
BeanPropertySqlParameterSource(bo);
//set DB table name
sji.setTableName("BANK_ACCOUNT");
//execute query by generating the query dynamically
int count = sji.execute(bpsps);
return count;
}
SimpleJdbcCall
A SimpleJdbcCall is a multi-threaded, reusable object representing a call
to a stored procedure or a stored function. It provides meta-data
processing to simplify the code needed to access basic stored
procedures/ functions. All you need to provide is the name of the
procedure/ function and a Map containing the parameters when you
execute the call. The names of the supplied parameters will be matched
up with in and out parameters declared when the stored procedure was
created.
Instead of writing same persistence logic/ business logic in multiple
modules as SQL queries/ Java code, it is recommended to write only for
1 time in DB s/w as stored procedure / function and use it multiple
modules.
PL/SQL procedure does not return a value but to get multiple results
from PL/SQL procedure we need to use multiple OUT params.
PL/SQL function returns a value. So, to get multiple results from PL/SQL
• Develop the above directory structure using maven setup and package,
class, XML file and add the jar dependencies to pom.xml, then use the
following code with in their respective file and Change to Java 1.9 or its
higher version.
• Copy the xml files and pom.xml from previous project.
IAuthenticationDAO.java
package com.nt.dao;
AuthenticationDAOImpl.java
package com.nt.dao;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Repository;
@Repository("authDAO")
public class AuthenticationDAOIml implements IAuthenticationDAO {
@Autowired
private SimpleJdbcCall sjc;
@Override
public String authentication(String user, String pwd) {
//Set procedure name
sjc.setProcedureName("P_AUTHENTICATION");
//prepare Map object of IN params
Map<String, ?> inParams = Map.of("UNAME", user, "PASS",
pwd);
//call PL/SQL procedure
Map<String, ?> outParams = sjc.execute(inParams);
return (String) outParams.get("RESULT");
}
LoginMgmtServiceImpl.java
package com.nt.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.nt.dao.IAuthenticationDAO;
@Service("loginService")
public class LoginMgmtServiceImpl implements ILoginMgmtService {
@Autowired
private IAuthenticationDAO dao;
@Override
public String login(String user, String pwd) {
//use DAO
String result=dao.authentication(user, pwd);
return result;
}
}
SimpleJdbcCallTest.java
package com.nt.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import com.nt.service.ILoginMgmtService;
public class SimpleJdbcCallTest {
On the each select SQL query related sub class obj of SqlQuery<T>/
MappingSqlQuery<T> we can call
@Autowired
public StudentDAOlmpl(DataSource ds){
selector1 = new StudentSelector1(ds,
GET_STUDENT_BY_ADDRS);
} //Constructor
Flow of execution:
• IoC container creation --> pre-instantiation of singleton scope beans so
DS, DAO classes pre-instantiated and DS is injected to DAO --> In that
process DAO constructor executes and calls sub class cum inner class
(StudentSelector1) constructor due to this sub class cum inner class
(StudentSelector1) gives DS, query to its super class (MappingSqlQuery)
only for 1 time and creates PreparedStatement object by making given
SQL query as pre-compiled Query because of super.compile() only for 1
time [At the end the sub class cum inner class (StudentSelector1)
represents pre-compiled SQL query].
• Service class method calls DAO method (getStudentsByAddrs(-)) for
multiple times, so selector1.execute(-) also called for multiple time --> ln
this process values to query params will be set for multiple times query
execution takes place for multiple times gathering RS object processing
that object to ListBO by calling mapRow (-, -) takes place for multiple
times --> returns ListBO back to DAO class method for multiple times.
BankAccountBO.java
package com.nt.bo;
import lombok.Data;
@Data
public class BankAccountBO {
private Long accNo;
private String holderName;
private Float balance;
private String status;
}
BankAccountDTO.java
package com.nt.dto;
import lombok.Data;
@Data
public class BankAccountDTO {
private Long accNo;
private String holderName;
private Float balance;
private String status;
}
BankDAOImpl.java
package com.nt.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.asm.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.MappingSqlQuery;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.stereotype.Repository;
import com.nt.bo.BankAccountBO;
@Repository("bankDAO")
public class BankDAOImpl implements IBankDAO {
private static final String GET_ACCOUNT_BY_BAL_RANGE="SELECT
ACCNO, HOLDERNAME, BALANCE, STATUS FROM BANK_ACCOUNT WHERE
BALANCE>=? AND BALANCE<=?";
private static final String GET_ACCOUNT_BY_ACCNO="SELECT
ACCNO, HOLDERNAME, BALANCE, STATUS FROM BANK_ACCOUNT WHERE
ACCNO=?";
private static final String UPDATE_BONUS_BY_BALANCE="UPDATE
BANK_ACCOUNT SET BALANCE=BALANCE+? WHERE BALANCE<?";
} //outer class
IBankMgmtService.java
package com.nt.service;
import java.util.List;
import com.nt.dto.BankAccountDTO;
@Override
public BankAccountDTO fetchBankAccountsByAccNo(long accno) {
// use dao
BankAccountBO bo = dao.getBankAccountByAccNo(accno);
//convert DTO to bo
BankAccountDTO dto = new BankAccountDTO();
BeanUtils.copyProperties(bo, dto);
return dto;
} 73 Prepared By - Nirmala Kumar Sahu
@Override
public String addBonusToBankAccountsByBalance(float bonus, float
return dto;
}
@Override
public String addBonusToBankAccountsByBalance(float bonus, float
maxBalance) {
//use dao
int count =
dao.updateBankAccountsWithBonusByBalance(bonus, maxBalance);
return count==0?"No accounts found for add bonus":count+"
No. of records are added with bonus:"+bonus;
}
}
IBankMgmtService.java
package com.nt.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import com.nt.service.IBankMgmtService;
public class MappingSQLOperationTest {
public static void main(String[] args) {
// Create IoC container
ApplicationContext ctx = new
ClassPathXmlApplicationContext("com/nt/cfgs/applicationContext.xml");
// get Service class object
IBankMgmtService service = ctx.getBean("bankService",
IBankMgmtService.class);
// invoke method
try {
System.out.println("Bank ACcounts having balance
Range 10000 to 20000");
service.fetchBankAccountsByBalanceRange(10000,
20000).forEach(System.out::println);
System.out.println("--------------------------");
74 Prepared By - Nirmala Kumar Sahu
System.out.println(service.fetchBankAccountsByAccNo(33232));
System.out.println("---------------------");
System.out.println("--------------------------");
System.out.println(service.fetchBankAccountsByAccNo(33232));
System.out.println("---------------------");
System.out.println(service.addBonusToBankAccountsByBalance(500,
10000));
} catch (DataAccessException dae) {
if (dae instanceof EmptyResultDataAccessException)
System.err.println("Record not found");
else if (dae instanceof BadSqlGrammarException)
System.err.println("SQL syntax problem");
else
System.err.println("other internal probelm");
dae.printStackTrace();
}
((AbstractApplicationContext) ctx).close();
}
}
Note:
✓ In spring boot application application.properties/ yml file will be
detected and loaded automatically as part application flow from
75 Prepared By - Nirmala Kumar Sahu
src/main/resources folder.
✓ The properties/ yml files having other name or location must be
configured explicitly using @PropertySource annotation.
application.properties
per.info.id=101
per.info.name=raja
@Component
@Data
public class Person {
@Value("${per.info.id}")
private int pid;
@Value("${per.info.name}")
private String pname;
}
import java.util.List;
import java.util.Map;
import java.util.Set;
import
org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
@Data
@Component("per")
@ConfigurationProperties(prefix = "per.info")
public class Person {
private int id;
private String name;
private int[] marks1;
private List<Integer> marks2;
private Set<Integer> marks3;
private Map<String, Integer> phones;
}
DaoBootProj02PropertiesFileValueConfigurationPropertyAnnotationApplicatio
n.java
package com.nt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.nt.model.Person;
@SpringBootApplication
public class
DaoBootProj02PropertiesFileValueConfigurationPropertyAnnotationApplica
tion {
application.properties
per.info.id=101
per.info.no=102
Person.java
@Data
@Component("per")
@ConfigurationProperties(prefix = "per.info")
public class Person {
@Value("${per.info.no}")
private int id;
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-
processor</artifactId>
<optional>true</optional>
</dependency>
Job.java
package com.nt.model;
import lombok.Data;
@Data
public class Job {
private String company;
private String desg;
private int deptno;
private float salary;
}
Person.java
@Data
@Component("per")
@ConfigurationProperties(prefix = "per.info")
public class Person {
Example
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware,
InitializingBean {
…………………
}
While preparing element values to array/ list/ set collection inline syntax
in properties file as shown below
application.properties
#Array/ Set/ List Collection [prefix.var[index]=value1,value2,valu3,…]
per.info.marks1=40,50,60
YML/ YAML
Yiant markup language/ Yamaling markup language (yml).
Yet Another Markup language (YAML).
Alternate to properties file, very useful when lengthy keys at same level
because it avoids duplicates from the keys by maintaining key and values
in hierarchy manner.
application.properties
info.per.id=101 The word "info.per" is repeated for multiple times
info.per.name=raja
in the keys there is duplication in the keys.
info.per.address=hyd
application.yml
info: level1 node
per: level2 node Here the word "info.per" is not repeated in the
id: 101 keys by maintain data as hierarchal data.
name: raja
address: hyd
application.yml
info:
per:
id: 101
name: raja
address: hyd
DaoBootProj03YmlValueConfigurationPropertyAnnotationApplication.java
package com.nt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.nt.model.Person;
@SpringBootApplication
public class
DaoBootProj03YmlValueConfigurationPropertyAnnotationApplication {
public static void main(String[] args) {
application.properties
info.per.id=101
info.per.name=raja
info.job.desg=clerk
info.job.salary=9000
company.location=hyd
company.name=HCL
application.yml
info:
per:
id: 101
name: raja
job:
desg: clerk Note: # symbol in properties file, yml file
salary: 9000 indicates comment.
company:
location: hyd
name: HCL
application.yml
info:
per: acts keys and values in map collection
phones: phones (Map collection)
residence: 999999
residence 999999
office: 888888
office 888888
personal: 777777
personal 777777
keys values
Person.java
@Data
@Component("per")
@ConfigurationProperties(prefix = "info.per")
public class Person {
private int id;
private String name;
private String address;
private int marks1[];
private List<Integer> marks2;
private Set<Integer> marks3;
private Map<String, Object> phones;
}
application.yml
info:
per:
#Simple properties
id: 101
name: raja
address: hyd
#Array
marks1:
- 30
- 40
85 Prepared By - Nirmala Kumar Sahu
- 50
#List
marks2:
- 40
- 50
#List
marks2:
- 40
- 50
- 60
#set
marks3:
- 50
- 60
- 70
#Map
phones:
residence: 9999999
office: 888888
personal: 777777
Use properties file if the keys are smaller and the nodes/ prefixes are no
repeating.
Use yml file if the keys are lengthy and the nodes/ prefixes are
repeating.
Note: Eclipse IDE there is bult-in convertor to given .properties file to .yml file
to right click on properties file -> convert .yml file.
Q. What is the differences and similarities between properties file and yml file.
Ans.
YAML(.YML) .PROPERTIES
Supports key/ value, basically map, Supports key/ value, but doesn’t
List and scalar types (int, string etc.). support values beyond the string.
If you are using spring profiles, you Each profile need one separate
can have multiple profiles in one .properties file.
single .yml file.
While retrieving the values from .yml While in case of the .properties
file we get the value as whatever the files we get strings regardless of
respective type (int, string etc.) is in what the actual value type is in
the configuration. the configuration.
Syntax:
application-<env/profile name>.properties (or) application-<env/profile>.yml
e.g.:
application.properties/ yml (base/default properties file)
application-dev.properties/yml (for dev env/profile)
application-test.properties/yml (for test env/profile)
application-uat.properties/yml (for uat env/profile)
application-prod.properties/yml (for production env/profile)
To make Spring Beans working for certain profile we can use @Profile
annotation on the top of stereotype annotation-based spring bean
classes or @Bean methods of @Configuration class.
@Profile({"uat","prod"})
@Repository("oraCustDAO")
public class OracleCustomerDAOlmpl implenents CustomerDAO {……}
@Configuration
@ComponentScan(basePackages="com.nt.dao")
public class PersistenceConfig {
@Bean
@Profile({"uat","test"}
public DataSource createApacheDBCPDS() {
…..
}
@Bean
@Profile("dev")
public DataSource createC3PODS() {
….
}
@Bean
@Profile("prod")
public DataSource createHKCPDS() {
……
}
}
application.yml
spring:
profiles:
active: dev
• In eclipse IDE Run As -> Run Configurations -> arguments tab -> program
arguments (command line args) -> VM arguments (system properties)
CustomerDTO.java
package com.nt.dto;
import java.io.Serializable;
import lombok.Data;
@Data
public class CustomerDTO implements Serializable{
private String cname;
private String cadd;
private float pAmt;
private float rate;
private float time;
}
CustomerDAO.java
package com.nt.dao;
import com.nt.bo.CustomerBO;
OracleCustomerDAOImpl.java
package com.nt.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.nt.bo.CustomerBO;
@Repository("oracleCustDAO")
public class OracleCustomerDAOImpl implements CustomerDAO {
private static final String CUSTOMER_INSERT_QUERY = "INSERT INTO
CUSTOMER_DB VALUES(CNO_SEQ.NEXTVAL,?,?,?,?)";
@Autowired
private JdbcTemplate jt;
@Override
public int insert(CustomerBO bo) throws Exception {
int count = jt.update(CUSTOMER_INSERT_QUERY,
95 Prepared By - Nirmala Kumar Sahu
bo.getCname(), bo.getCadd(), bo.getPAmnt(), bo.getInterAmt());
return count;
public int insert(CustomerBO bo) throws Exception {
int count = jt.update(CUSTOMER_INSERT_QUERY,
bo.getCname(), bo.getCadd(), bo.getPAmnt(), bo.getInterAmt());
return count;
}
}
CustomerMgmtService.java
package com.nt.service;
import com.nt.dto.CustomerDTO;
public interface CustomerMgmtService {
public String calculateSimpleInterestAmount(CustomerDTO dto)
throws Exception;
}
MySQLCustomerMgmtServiceImpl.java
package com.nt.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import com.nt.bo.CustomerBO;
import com.nt.dao.CustomerDAO;
import com.nt.dto.CustomerDTO;
@Service("custService")
@Profile({"dev", "test"})
public final class MySQLCustomerMgmtServiceImpl implements
CustomerMgmtService {
@Autowired
@Qualifier("mysqlCustDAO")
private CustomerDAO dao;
@Override
public String calculateSimpleInterestAmount(CustomerDTO dto)
throws Exception {
float interAmt = 0.f;
CustomerBO bo = null;
int count = 0; 96 Prepared By - Nirmala Kumar Sahu
//Calculate the simple interest amount from DTO
interAmt = (dto.getPAmt()*dto.getTime()*dto.getRate())/100;
CustomerBO bo = null;
int count = 0;
//Calculate the simple interest amount from DTO
interAmt = (dto.getPAmt()*dto.getTime()*dto.getRate())/100;
//Prepare CustomerBO having persist able Data
bo = new CustomerBO();
bo.setCname(dto.getCname());
bo.setCadd(dto.getCadd());
bo.setPAmnt(dto.getPAmt());
bo.setInterAmt(interAmt);
//use the dao
count = dao.insert(bo);
if (count==0)
return "Customer registration failed - Insert amount is :
"+interAmt;
else
return "Customer registration succeded - Insert amount
is : "+interAmt;
}
}
OracleCustomerMgmtServiceImpl.java
package com.nt.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import com.nt.bo.CustomerBO;
import com.nt.dao.CustomerDAO;
import com.nt.dto.CustomerDTO;
@Service("custService")
@Profile({"uat", "prod"})
public final class OracleCustomerMgmtServiceImpl implements
CustomerMgmtService {
@Autowired
@Qualifier("oracleCustDAO")
private CustomerDAO dao;
MainController.java
package com.nt.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.nt.dto.CustomerDTO;
import com.nt.service.CustomerMgmtService;
import com.nt.vo.CustomerVO;
@Controller("controller")
public final class MainController {
@Autowired
private CustomerMgmtService service;
public String processCustomer(CustomerVO vo) throws Exception {
CustomerDTO dto = null;
String result = null; 98 Prepared By - Nirmala Kumar Sahu
//covert Customer VO to customer DTO
dto = new CustomerDTO();
CustomerDTO dto = null;
String result = null;
//covert Customer VO to customer DTO
dto = new CustomerDTO();
dto.setCname(vo.getCname());
dto.setCadd(vo.getCadd());
dto.setPAmt(Float.parseFloat(vo.getPAmt()));
dto.setTime(Float.parseFloat(vo.getTime()));
dto.setRate(Float.parseFloat(vo.getRate()));
//use Service
result = service.calculateSimpleInterestAmount(dto);
return result;
}
}
application.properties
#Activate Profile
spring.profiles.active=dev
application-uat.properties
#DataSource configuration For uat. (Oracle, ApacheDBCP)
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=system
spring.datasource.password=manager
application-test.properties
#DataSource configuration For Test Env. (MySQL, ApacheDBCP)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///nssp713db
spring.datasource.username=root
spring.datasource.password=root
application-dev.properties
#DataSource configuration For Dev. Env. (MySQL, C3P0)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///nssp713db
spring.datasource.username=root
spring.datasource.password=root
DAOBootProj04MiniProjectUsingProfileApplication.java
package com.nt;
import java.util.Scanner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import com.nt.controller.MainController;
import com.nt.vo.CustomerVO;
@SpringBootApplication
public class DAOBootProj04MiniProjectUsingProfileApplication {
public static void main(String[] args) {
ApplicationContext ctx = null;
MainController controller = null;
String name=null, address=null, Amount=null, time=null,
rate=null;
CustomerVO vo = null;
String result = null;
Scanner sc = null;
//Read inputs from end-user using scanner
sc = new Scanner(System.in);
100 the following
System.out.println("Enter Prepared
DetailsByfor
- Nirmala Kumar Sahu
registration :
");
System.out.print("Enter Customer Name : ");
sc = new Scanner(System.in);
System.out.println("Enter the following Details: ");
System.out.print("Enter Customer Name : ");
name = sc.next();
System.out.print("Enter Customer Address : ");
address = sc.next();
System.out.print("Enter Customer Principle Amount : ");
Amount = sc.next();
System.out.print("Enter Customer Time : ");
time = sc.next();
System.out.print("Enter Customer Rate of Interest: ");
rate = sc.next();
//Store into VO class object
vo = new CustomerVO();
vo.setCname(name);
vo.setCadd(address);
vo.setPAmt(Amount);
vo.setTime(time);
vo.setRate(rate);
//get controller class object
//get container
ctx =
SpringApplication.run(DAOBootProj04MiniProjectUsingProfileApplication.cl
ass, args);
//get controller class
controller = ctx.getBean("controller", MainController.class);
//invoke methods
try {
result = controller.processCustomer(vo);
System.out.println(result);
} catch (Exception e) {
System.out.println("Internal probelm :
"+e.getMessage());
e.printStackTrace();
}
//close container
((AbstractApplicationContext) ctx).close();
}
application.yml
spring:
profiles:
active: dev
application-uat.yml
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
password: manager
type: org.apache.commons.dbcp2.BasicDataSource
url: jdbc:oracle:thin:@localhost:1521:xe
username: system
application-test.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: root
type: org.apache.commons.dbcp2.BasicDataSource
url: jdbc:mysql:///nssp713db
username: root
application-prod.yml
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
password: manager
url: jdbc:oracle:thin:@localhost:1521:xe
username: system
application.yml
#Dev
spring:
profiles: dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: root
type: com.mchange.v2.c3p0.ComboPooledDataSource
url: jdbc:mysql:///nssp713db
username: root
--- #Acts as a separator
#Prod
spring:
profiles: prod
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
password: manager
url: jdbc:oracle:thin:@localhost:1521:xe
username: system
---
#Test
spring:
profiles: test
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: root 103 Prepared By - Nirmala Kumar Sahu
type: org.apache.commons.dbcp2.BasicDataSource
url: jdbc:mysql:///nssp713db
username: root
driver-class-name: com.mysql.cj.jdbc.Driver
password: root
type: org.apache.commons.dbcp2.BasicDataSource
url: jdbc:mysql:///nssp713db
username: root
---
#Uat
spring:
profiles: uat
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
password: manager
type: org.apache.commons.dbcp2.BasicDataSource
url: jdbc:oracle:thin:@localhost:1521:xe
username: system
---
#Base
spring:
profiles:
active: dev
Note: If you don’t put Spring bean in any profile then it will be used for all
profiles in out mini project, we can use all Service, Controller classes without
placing in profiles to make them common for all profiles.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({PersistenceConfig.class, ServiceConfig.class,
ControllerConfig.class})
public class AppConfig {
PersistenceConfig.java
package com.nt.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
@ComponentScan(basePackages = "com.nt.dao")
public class PersistenceConfig {
@Bean
@Profile("dev")
public DataSource createC3P0DS() throws Exception {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///nssp713db");
ds.setUser("root");
ds.setPassword("root");
return ds;
}
@Bean
@Profile("test")
public DataSource createApacheDBCPDSMySQL() throws Exception {
BasicDataSource bds = 106 Prepared By - Nirmala Kumar Sahu
new BasicDataSource();
bds.setDriverClassName("com.mysql.cj.jdbc.Driver");
bds.setUrl("jdbc:mysql:///nssp713db");
public DataSource createApacheDBCPDSMySQL() throws Exception {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("com.mysql.cj.jdbc.Driver");
bds.setUrl("jdbc:mysql:///nssp713db");
bds.setUsername("root");
bds.setPassword("root");
return bds;
}
@Bean
@Profile("uat")
public DataSource createApacheDBCPDSOracle() throws Exception {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
bds.setUsername("system");
bds.setPassword("manager");
return bds;
}
@Bean
@Profile("prod")
public DataSource createHikariCPDS() throws Exception {
HikariDataSource hds = new HikariDataSource();
hds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
hds.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
hds.setUsername("system");
hds.setPassword("manager");
return hds;
}
@Bean
@Profile("dev")
public JdbcTemplate createJTUsingC3PODS() throws Exception {
return new JdbcTemplate(createC3P0DS());
}
@Bean
@Profile("test")
public JdbcTemplate createJTUsingApacheDPCPDSWithMySQL()
throws Exception {
return new JdbcTemplate(createApacheDBCPDSMySQL());
}
107 Prepared By - Nirmala Kumar Sahu
@Bean
@Profile("uat")
public JdbcTemplate createJTUsingApacheDPCPDSWithOracle()
}
@Bean
@Profile("uat")
public JdbcTemplate createJTUsingApacheDPCPDSWithOracle()
throws Exception {
return new JdbcTemplate(createApacheDBCPDSOracle());
}
@Bean
@Profile("prod")
public JdbcTemplate createJTUsingHikariCPDS() throws Exception {
return new JdbcTemplate(createHikariCPDS());
}
}
ServiceConfig.java
package com.nt.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.nt.service")
public class ServiceConfig {
}
MySQLCustomerDAOImpl.java
@Repository("mysqlCustDAO")
@Profile({"dev", "test"})
public class MySQLCustomerDAOImpl implements CustomerDAO {
OracleCustomerDAOImpl.java
@Repository("mysqlCustDAO")
@Profile({"uat", "prod"})
public class OracleCustomerDAOImpl implements CustomerDAO {
@Autowired
private CustomerDAO dao;
RealTimeDITest.java
package com.nt.test;
import java.util.Scanner;
import
org.springframework.context.annotation.AnnotationConfigApplicationCont
ext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.nt.config.AppConfig;
import com.nt.controller.MainController;
import com.nt.vo.CustomerVO;
public class RealTimeDITest {
build.gradle
plugins {
// Apply the java-library plugin to add support for Java Library
id 'application'
}
mainClassName = 'com.nt.test.RealTimeDITest'
org.sf.core.env.Enviroment(l)
| extends
org.sf.core.env.ConfigurableEnviroment (I)
jdbc.properties
#For MySQL
jdbc.mysql.driverclass=com.mysql.cj.jdbc.Driver
jdbc.mysql.url=jdbc:mysql:///nssp713db
jdbc.mysql.username=root
jdbc.mysql.password=root
#For Oracle
jdbc.oracle.driverclass=oracle.jdbc.driver.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.oracle.username=system
jdbc.oracle.password=manager
PersisteneConfig.java
package com.nt.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mchange.v2.c3p0.ComboPooledDataSource;
112 Prepared By - Nirmala Kumar Sahu
import com.zaxxer.hikari.HikariDataSource;
@Configuration
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
@ComponentScan(basePackages = "com.nt.dao")
@PropertySource("com/nt/commons/jdbc.properties")
public class PersistenceConfig {
@Autowired
private Environment env;
@Bean
@Profile("dev")
public DataSource createC3P0DS() throws Exception {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(env.getProperty("jdbc.mysql.driverclass"));
ds.setJdbcUrl(env.getProperty("jdbc.mysql.url"));
ds.setUser(env.getProperty("jdbc.mysql.username"));
ds.setPassword(env.getProperty("jdbc.mysql.password"));
return ds;
}
@Bean
@Profile("test")
public DataSource createApacheDBCPDSMySQL() throws Exception {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(env.getProperty("jdbc.mysql.driverclass"));
bds.setUrl(env.getProperty("jdbc.mysql.url"));
bds.setUsername(env.getProperty("jdbc.mysql.username"));
bds.setPassword(env.getProperty("jdbc.mysql.password"));
return bds;
}
@Bean
@Profile("uat")
public DataSource createApacheDBCPDSOracle() throws Exception {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName(env.getProperty("jdbc.oracle.driverclass"));
bds.setUrl(env.getProperty("jdbc.oracle.url"));
bds.setUsername(env.getProperty("jdbc.oracle.username"));
bds.setPassword(env.getProperty("jdbc.oracle.password"));
return bds; 113 Prepared By - Nirmala Kumar Sahu
}
@Bean
bds.setPassword(env.getProperty("jdbc.oracle.password"));
return bds;
}
@Bean
@Profile("prod")
public DataSource createHikariCPDS() throws Exception {
HikariDataSource hds = new HikariDataSource();
hds.setDriverClassName(env.getProperty("jdbc.oracle.driverclass"));
hds.setJdbcUrl(env.getProperty("jdbc.oracle.url"));
hds.setUsername(env.getProperty("jdbc.oracle.username"));
hds.setPassword(env.getProperty("jdbc.oracle.password"));
return hds;
}
@Bean(autowire = Autowire.BY_TYPE)
public JdbcTemplate createJT() throws Exception {
return new JdbcTemplate();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<import resource="persistence-beans-dev.xml"/>
<import resource="persistence-beans-test.xml"/>
<import resource="persistence-beans-uat.xml"/>
115 Prepared By - Nirmala Kumar Sahu
<import resource="persistence-beans-prod.xml"/>
<import resource="service-beans.xml"/>
<import resource="controller-beans.xml"/>
<import resource="persistence-beans-uat.xml"/>
<import resource="persistence-beans-prod.xml"/>
<import resource="service-beans.xml"/>
<import resource="controller-beans.xml"/>
</beans>
controller-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="com.nt.controller"/>
</beans>
service-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="com.nt.service"/>
</beans>
persistence-beans-dev.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans profile="dev"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
116 Prepared By - Nirmala Kumar Sahu
<bean id="c3p0DS"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="c3p0DS"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"
value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///nssp713db"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="c3p0DS"/>
</bean>
<context:component-scan base-package="com.nt.dao"/>
</beans>
persistence-beans-prod.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans profile="prod"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="hikariCPDS" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl"
value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="username" value="system"/>
<property name="password" value="manager"/>
</bean>
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="hikariCPDS"/>
</bean>
<context:component-scan base-package="com.nt.dao"/>
</beans>
persistence-beans-uat.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans profile="uat"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/bean
s https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="dpcpDS"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:@localhost:1521:xe" />
118 Prepared By - Nirmala Kumar Sahu
<property name="username" value="system"/>
<property name="password" value="manager"/>
</bean>
value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="username" value="system"/>
<property name="password" value="manager"/>
</bean>
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dpcpDS"/>
</bean>
<context:component-scan base-package="com.nt.dao" />
</beans>
persistence-beans-uat.xml
package com.nt.test;
import java.util.Scanner;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.nt.controller.MainController;
import com.nt.vo.CustomerVO;
public class RealTimeDITest {
} //main
} //class