Let's play and learn more about Spring JDBC, JPA and Spring Data JPA
- Step 01 - Setting up a project with JDBC, JPA, H2 and Web Dependencies
- Step 02 - Launching up H2 Console
- Step 03 - Creating a Database Table in H2
- Step 04 - Populate data into Person Table
- Step 05 - Implement findAll persons Spring JDBC Query Method
- Step 06 - Execute the findAll method using CommandLineRunner
- Step 07 - A Quick Review - JDBC vs Spring JDBC
- Step 08 - Whats in the background? Understanding Spring Boot Autoconfiguration
- Step 09 - Implementing findById Spring JDBC Query Method
- Step 10 - Implementing deleteById Spring JDBC Update Method
- Step 11 - Implementing insert and update Spring JDBC Update Methods
- Step 12 - Creating a custom Spring JDBC RowMapper
- Step 13 - Quick introduction to JPA
- Step 14 - Defining Person Entity
- Step 15 - Implementing findById JPA Repository Method
- Step 16 - Implementing insert and update JPA Repository Methods
- Step 17 - Implementing deleteById JPA Repository Method
- Step 18 - Implementing findAll using JPQL Named Query
=========================
AUTO-CONFIGURATION REPORT
=========================
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
DataSourceTransactionManagerAutoConfiguration matched:
- @ConditionalOnClass found required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.transaction.PlatformTransactionManager'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
H2ConsoleAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.h2.server.web.WebServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
- @ConditionalOnProperty (spring.h2.console.enabled=true) matched (OnPropertyCondition)
JdbcTemplateAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.core.JdbcTemplate'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a primary bean from beans 'dataSource' (OnBeanCondition)
JdbcTemplateAutoConfiguration.JdbcTemplateConfiguration#jdbcTemplate matched:
- @ConditionalOnMissingBean (types: org.springframework.jdbc.core.JdbcOperations; SearchStrategy: all) did not find any beans (OnBeanCondition)
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.in28minutes.database</groupId>
<artifactId>database-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>database-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
package com.in28minutes.database.databasedemo.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
@Entity
@NamedQuery(name="find_all_persons", query="select p from Person p")
public class Person {
@Id
@GeneratedValue
private int id;
private String name;
private String location;
private Date birthDate;
public Person() {
}
public Person(int id, String name, String location, Date birthDate) {
super();
this.id = id;
this.name = name;
this.location = location;
this.birthDate = birthDate;
}
public Person(String name, String location, Date birthDate) {
super();
this.name = name;
this.location = location;
this.birthDate = birthDate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
@Override
public String toString() {
return String.format("\nPerson [id=%s, name=%s, location=%s, birthDate=%s]", id, name, location, birthDate);
}
}
package com.in28minutes.database.databasedemo.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.in28minutes.database.databasedemo.entity.Person;
@Repository
public class PersonJbdcDao {
@Autowired
JdbcTemplate jdbcTemplate;
class PersonRowMapper implements RowMapper<Person>{
@Override
public Person mapRow(ResultSet rs, int rowNum) throws SQLException {
Person person = new Person();
person.setId(rs.getInt("id"));
person.setName(rs.getString("name"));
person.setLocation(rs.getString("location"));
person.setBirthDate(rs.getTimestamp("birth_date"));
return person;
}
}
public List<Person> findAll() {
return jdbcTemplate.query("select * from person", new PersonRowMapper());
}
public Person findById(int id) {
return jdbcTemplate.queryForObject("select * from person where id=?", new Object[] { id },
new BeanPropertyRowMapper<Person>(Person.class));
}
public int deleteById(int id) {
return jdbcTemplate.update("delete from person where id=?", new Object[] { id });
}
public int insert(Person person) {
return jdbcTemplate.update("insert into person (id, name, location, birth_date) " + "values(?, ?, ?, ?)",
new Object[] { person.getId(), person.getName(), person.getLocation(),
new Timestamp(person.getBirthDate().getTime()) });
}
public int update(Person person) {
return jdbcTemplate.update("update person " + " set name = ?, location = ?, birth_date = ? " + " where id = ?",
new Object[] { person.getName(), person.getLocation(), new Timestamp(person.getBirthDate().getTime()),
person.getId() });
}
}
package com.in28minutes.database.databasedemo.jpa;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import org.springframework.stereotype.Repository;
import com.in28minutes.database.databasedemo.entity.Person;
@Repository
@Transactional
public class PersonJpaRepository {
// connect to the database
@PersistenceContext
EntityManager entityManager;
public List<Person> findAll() {
TypedQuery<Person> namedQuery = entityManager.createNamedQuery("find_all_persons", Person.class);
return namedQuery.getResultList();
}
public Person findById(int id) {
return entityManager.find(Person.class, id);// JPA
}
public Person update(Person person) {
return entityManager.merge(person);
}
public Person insert(Person person) {
return entityManager.merge(person);
}
public void deleteById(int id) {
Person person = findById(id);
entityManager.remove(person);
}
}
package com.in28minutes.database.databasedemo;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.in28minutes.database.databasedemo.entity.Person;
import com.in28minutes.database.databasedemo.jpa.PersonJpaRepository;
@SpringBootApplication
public class JpaDemoApplication implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
PersonJpaRepository repository;
public static void main(String[] args) {
SpringApplication.run(JpaDemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
logger.info("User id 10001 -> {}", repository.findById(10001));
logger.info("Inserting -> {}",
repository.insert(new Person("Tara", "Berlin", new Date())));
logger.info("Update 10003 -> {}",
repository.update(new Person(10003, "Pieter", "Utrecht", new Date())));
repository.deleteById(10002);
logger.info("All users -> {}", repository.findAll());
}
}
package com.in28minutes.database.databasedemo;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.in28minutes.database.databasedemo.entity.Person;
import com.in28minutes.database.databasedemo.jdbc.PersonJbdcDao;
//@SpringBootApplication
public class SpringJdbcDemoApplication implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
PersonJbdcDao dao;
public static void main(String[] args) {
SpringApplication.run(SpringJdbcDemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
logger.info("All users -> {}", dao.findAll());
logger.info("User id 10001 -> {}", dao.findById(10001));
logger.info("Deleting 10002 -> No of Rows Deleted - {}",
dao.deleteById(10002));
logger.info("Inserting 10004 -> {}",
dao.insert(new Person(10004, "Tara", "Berlin", new Date())));
logger.info("Update 10003 -> {}",
dao.update(new Person(10003, "Pieter", "Utrecht", new Date())));
}
}
spring.h2.console.enabled=true
spring.jpa.show-sql=true
#logging.level.root=debug
/*
create table person
(
id integer not null,
name varchar(255) not null,
location varchar(255),
birth_date timestamp,
primary key(id)
);
*/
INSERT INTO PERSON (ID, NAME, LOCATION, BIRTH_DATE )
VALUES(10001, 'Ranga', 'Hyderabad',sysdate());
INSERT INTO PERSON (ID, NAME, LOCATION, BIRTH_DATE )
VALUES(10002, 'James', 'New York',sysdate());
INSERT INTO PERSON (ID, NAME, LOCATION, BIRTH_DATE )
VALUES(10003, 'Pieter', 'Amsterdam',sysdate());
package com.in28minutes.database.databasedemo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringJdbcDemoApplicationTests {
@Test
public void contextLoads() {
}
}