Showing posts with label h2. Show all posts
Showing posts with label h2. Show all posts

Tuesday, 1 November 2022

Hibernate 6: H2 Hello world application

Follow below step-by-step procedure to connect to H2 database using Hibernate.

 

Step 1: Create new maven project ‘hibernate-h2-hello-world’.

 

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>hibernate-h2-hello-world</artifactId>
    <version>1</version>

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

        <java.version>15</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

    </properties>

    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.1.214</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.1.2.Final</version>
        </dependency>

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>


    </dependencies>
</project>

 

Step 3: Define Employee entity class.

 

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

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

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

    public Employee() {
    }

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

    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 String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public int getAge() {
        return age;
    }

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

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

}

 

Step 4: Create hibernate.cfg.xml file under src/main/resources folder.

 

hibernate.cfg.xml

 

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="connection.driver_class">org.h2.Driver</property>
        <property name="connection.url">jdbc:h2:mem:test</property>
        <property name="connection.username">admin</property>
        <property name="connection.password">admin</property>
        <property name="connection.pool_size">1</property>

        <property name="dialect">org.hibernate.dialect.H2Dialect</property>
        <!-- Echo the SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="current_session_context_class">thread</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create-drop</property>
        
        <!-- dbcp connection pool configuration -->
        <property name="hibernate.dbcp.initialSize">2</property>
        <property name="hibernate.dbcp.maxTotal">10</property>
        <property name="hibernate.dbcp.maxIdle">5</property>
        <property name="hibernate.dbcp.minIdle">3</property>
        <property name="hibernate.dbcp.maxWaitMillis">-1</property>

        <!-- mappings for annotated classes -->
        <mapping class="com.sample.app.entity.Employee" />

    </session-factory>

</hibernate-configuration>

 

Step 5: Define main application class.

 

App.java

package com.sample.app;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import com.sample.app.entity.Employee;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;

public class App {
    private static SessionFactory sessionFactory = buildSessionFactory();

    private static <T> List<T> loadAllData(Class<T> clazz, Session session) {
        final CriteriaBuilder builder = session.getCriteriaBuilder();
        final CriteriaQuery<T> criteria = builder.createQuery(clazz);
        criteria.from(clazz);
        return session.createQuery(criteria).getResultList();
    }

    private static SessionFactory buildSessionFactory() {
        try {
            if (sessionFactory == null) {
                StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                        .configure("hibernate.cfg.xml").build();

                Metadata metaData = new MetadataSources(standardRegistry).getMetadataBuilder().build();

                sessionFactory = metaData.getSessionFactoryBuilder().build();
            }
            return sessionFactory;
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static void main(String args[]) throws ClassNotFoundException, IOException, URISyntaxException {
        Employee emp1 = new Employee(1, "Krishna", "G", "Senior Software Developer", 26);
        Employee emp2 = new Employee(2, "Shreyas", "Desai", "Team Manager", 35);
        Employee emp3 = new Employee(3, "Piyush", "Rai", "Senior Software Developer", 26);
        Employee emp4 = new Employee(4, "Maruti", "Borker", "Software Developer", 26);

        try (Session session = sessionFactory.openSession()) {
            session.beginTransaction();
            session.persist(emp1);
            session.persist(emp2);
            session.persist(emp3);
            session.persist(emp4);

            List<Employee> emps = loadAllData(Employee.class, session);
            for (Employee emp : emps) {
                System.out.println(emp);
            }

            session.getTransaction().commit();
        }

    }
}

 

Total project structure looks like below.

 


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

Aug 17, 2022 7:57:46 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.h2.Driver
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:h2:mem:test]
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=admin}
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 1 (min=1)
Aug 17, 2022 7:57:46 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: 
    
    drop table if exists employees cascade 
Aug 17, 2022 7:57:47 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@3e5fd2b1] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: 
    
    create table employees (
       id integer not null,
        age integer not null,
        designation varchar(255),
        firstName varchar(255),
        lastName varchar(255),
        primary key (id)
    )
Aug 17, 2022 7:57:47 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@23a918c7] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: 
    insert 
    into
        employees
        (age, designation, firstName, lastName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        employees
        (age, designation, firstName, lastName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        employees
        (age, designation, firstName, lastName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        employees
        (age, designation, firstName, lastName, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    select
        e1_0.id,
        e1_0.age,
        e1_0.designation,
        e1_0.firstName,
        e1_0.lastName 
    from
        employees e1_0
Employee [id=1, firstName=Krishna, lastName=G, designation=Senior Software Developer, age=26]
Employee [id=2, firstName=Shreyas, lastName=Desai, designation=Team Manager, age=35]
Employee [id=3, firstName=Piyush, lastName=Rai, designation=Senior Software Developer, age=26]
Employee [id=4, firstName=Maruti, lastName=Borker, designation=Software Developer, age=26]

You can download complete working application from this link.




 

 

 

  

Previous                                                    Next                                                    Home

Saturday, 3 August 2019

Spring boot: Configuring Data Source


This is continuous to my previous application. You can download previous working application from this link.

I am going to use H2 embeddable data base to store the data. If you want to learn more about H2 database, I would recommend you to go through my below post.

Note:
Clear the VM argument ‘-Dspring.profiles.active=prod’ that we added in previous step.

Step 1: Add dependencies for spring data jpa and H2 database.
 <dependencies>
 
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

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

  <!-- 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>

Step 2: Update application.properties with following content.

application.properties
# Setting log level to DEBUG
logging.level.org.springframework.web=DEBUG

# Application launch at this port
server.port=8080

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

spring.datasource.url=jdbc:h2:file:~/db/myDatabase.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
spring.jpa.hibernate.ddl-auto=update

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

H2 console is only intended for use during development, so you should take care to ensure that spring.h2.console.enabled is not set to true in production.

By default, the console is available at /h2-console. You can customize the console’s path by using the spring.h2.console.path property.

Step 3: Run App.java application.


Since we configured H2 database console path to /h2, ppen the url ‘http://localhost:8080/h2/’ in browser to see H2 console.

Spring boot configures H2 database with default values.

Update JDBC URL User Name and Password values from application.properties.


Click on Connect button.

Go to you home directory, you can see that there is a folder named ‘db’ is created.

$tree db
db
└── myDatabase.db.mv.db

0 directories, 1 file

Step 4: Adding JPA specific configurations on Employee model class.

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

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

@Entity
public class Employee {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String firstName;
 private String 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;
 }

}

Step 5: Define EmployeeRepository interface like below.

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

import org.springframework.data.repository.CrudRepository;

import com.sample.app.model.Employee;  

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {

 
}

Since Employee table has an integer as primary key, we should extend CrudRepository<Employee, Integer> interface.

Step 6: Define EmployeeService class like below.

EmployeeService.java
package com.sample.app.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class EmployeeService {

 @Autowired
 private EmployeeRepository employeeRepository;

 public List<Employee> getAllEmployees() {
  List<Employee> emps = new ArrayList<>();
  employeeRepository.findAll().forEach(emps::add);
  return emps;
 }

 public Optional<Employee> getEmployee(int id) {
  return employeeRepository.findById(id);
 }

 public Employee createEmployee(Employee emp) {
  return employeeRepository.save(emp);
 }

 public Employee deleteEmployee(int id) {
  Optional<Employee> emp = employeeRepository.findById(id);
  
  if(!emp.isPresent()) {
   return null;
  }
  
  Employee returnedEmp = emp.get();
  employeeRepository.deleteById(id);
  return returnedEmp;
 }

 public Employee updateEmployee(Employee emp) {
  Optional<Employee> persistedEmp = employeeRepository.findById(emp.getId());

  if (!persistedEmp.isPresent()) {
   return null;
  }

  Employee employeeFromDB = persistedEmp.get();
  employeeFromDB.setFirstName(emp.getFirstName());
  employeeFromDB.setLastName(emp.getLastName());

  return employeeRepository.save(employeeFromDB);

 }
}

Step 7: Update EmployeeController class like below.

EmployeeController.java
package com.sample.app.controller;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.sample.app.model.Employee;
import com.sample.app.service.EmployeeService;

@RestController
@RequestMapping("api/v1/")
public class EmployeeController {

 @Autowired
 private EmployeeService empService;

 @RequestMapping(value = "employees", method = RequestMethod.GET)
 public ResponseEntity<List<Employee>> all() {
  return ResponseEntity.ok(empService.getAllEmployees());
 }

 @RequestMapping(value = "employees", method = RequestMethod.POST)
 public ResponseEntity<Employee> create(@RequestBody Employee emp) {
  return new ResponseEntity<>(empService.createEmployee(emp), HttpStatus.CREATED);

 }

 @RequestMapping(value = "employees/{id}", method = RequestMethod.GET)
 public ResponseEntity<Employee> byId(@PathVariable int id) {
  Optional<Employee> emp = empService.getEmployee(id);

  if (!emp.isPresent()) {
   return new ResponseEntity<>(HttpStatus.NOT_FOUND);
  }

  return ResponseEntity.ok(emp.get());

 }

 @RequestMapping(value = "employees/{id}", method = RequestMethod.DELETE)
 public ResponseEntity<Employee> deleteById(@PathVariable int id) {

  Employee emp = empService.deleteEmployee(id);

  if (emp == null) {
   return new ResponseEntity<>(HttpStatus.NOT_FOUND);
  }

  return ResponseEntity.ok(emp);
 }

 @RequestMapping(value = "employees/{id}", method = RequestMethod.PUT)
 public ResponseEntity<Employee> updateById(@PathVariable int id, @RequestBody Employee emp) {

  emp.setId(id);
  Employee updatedEmployee = empService.updateEmployee(emp);

  if (updatedEmployee == null) {
   return new ResponseEntity<>(HttpStatus.NOT_FOUND);
  }

  return ResponseEntity.ok(updatedEmployee);
 }

}


App.java
package com.sample.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

Run App.java.


Open the url ‘http://localhost:8080/h2’.


Enter password as ‘password123’ and click on Connect button.

As you see left side of the window, EMPLOYEE table is created.

Let’s insert new employee by hitting below request.

Method: POST
Payload:
{
    "firstName" : "Joel",
    "lastName" : "Chelli"
}

Once you hit the request, you will receive below response.

{
    "id": 1,
    "firstName": "Joel",
    "lastName": "Chelli"
}

Hit below request to retrieve all the employees from database.

API: http://localhost:8080/api/v1/employees
Method: GET

Once you hit above request, you will receive below response.
[
    {
        "id": 1,
        "firstName": "Joel",
        "lastName": "Chelli"
    }
]

That’s it….you are done. In my next post, I am going to explain how to test the spring boot application.

You can download complete working application from below github link.

Total project structure looks like below.


Note
a.   As part of spring-boot auto configuration, it uses tomcat-jdbc as default connection pooling strategy.
b.   Spring boot also support other connection pooling libraries like Hikari CP, Commons DBCP, Commons DBCP2.



Previous                                                    Next                                                    Home