ZetCode

Hibernate Derby

last modified August 31, 2020

Hibernate Derby tutorial shows how to use the Hibernate ORM with the Derby database.

Hibernate

Hibernate is an object-relational mapping framework for the Java language. It provides a framework for mapping an object-oriented domain model to a relational database. Object-relational mapping (ORM) is a programming technique for converting data between incompatible type systems in object-oriented programming languages.

Hibernate Query Language (HQL) is an object-oriented query language similar to SQL. While SQL operates on tables and columns, HQL operates on persistent objects and their properties. HQL understands inheritance, polymorphism, and association. HQL queries are in the end translated by Hibernate into SQL queries, which do some action on the database.

In addition to its native API, Hibernate contains an implementation of the Java Persistence API (JPA).

Apache Derby

Apache Derby is an is an open source relational database implemented entirely in Java. Derby has a small footprint and is easy to deploy and install. It supports both embedded and client/server modes.

Hibernate artifacts

The hibernate.cfg.xml file defines the Hibernate configuration information. It contains information about the database connection, resource mappings, and other connection properties.

SessionFactory is the factory class through which we get sessions and perform database operations. Session is the main runtime interface between a Java application and Hibernate. The main function of the session is to offer create, read, and delete operations for instances of mapped entity classes.

Creating a database in Derby

We download Derby from the https://downloads.apache.org/db/derby/ webpage. We unpack the file into a chosen directory.

~/bin/derby-10.15$ ls
bin  demo  derby_cars.sql  derby.log  docs  index.html  javadoc  KEYS  lib
LICENSE  NOTICE  RELEASE-NOTES.html  test  testdb

These are the contents of the Derby installation directory.

~/bin/derby-10.15$ java -jar lib/derbyrun.jar sysinfo
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
------------------ Java Information ------------------
Java Version:    13.0.4
Java Vendor:     Debian
Java home:       /usr/lib/jvm/java-13-openjdk-amd64
Java classpath:  lib/derbyrun.jar
OS name:         Linux
OS architecture: amd64
...

We get the system information.

We create a new testdb database in Derby. It will have a simple cars table.

cars_derby.sql
CREATE TABLE cars(id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY
    (START WITH 1, INCREMENT BY 1), name VARCHAR(255), price INT);

INSERT INTO cars(name, price) VALUES('Audi', 52642);
INSERT INTO cars(name, price) VALUES('Mercedes', 57127);
INSERT INTO cars(name, price) VALUES('Skoda', 9000);
INSERT INTO cars(name, price) VALUES('Volvo', 29000);
INSERT INTO cars(name, price) VALUES('Bentley', 350000);
INSERT INTO cars(name, price) VALUES('Citroen', 21000);
INSERT INTO cars(name, price) VALUES('Hummer', 41400);
INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);

This is the SQL to create the cars table; the id of the car object is auto-incremented.

~/bin/derby-10.15$ java -jar lib/derbyrun.jar ij
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ij version 10.15
ij> CONNECT 'jdbc:derby:testdb;user=user7;create=true';

We run the ij tool and create the testdb database.

ij> RUN 'cars_derby.sql'

We run the RUN command, we create the cars table.

~/bin/derby-10.15$ bin/startNetworkServer &

We start the database with the startNetworkServer command.

Derby with native Hibernate API and XML mapping

In this section, we create a Java console application that performs some database tasks on a Derby database. We use the Hibernate native API and XML mapping.

pom.xml
src
├── main
│   ├── java
│   │   └── com
│   │       └── zetcode
│   │           ├── bean
│   │           │   └── Car.java
│   │           ├── hibernate
│   │           │   └── Car.hbm.xml
│   │           ├── main
│   │           │   └── HibernateDerbyEx.java
│   │           ├── service
│   │           │   └── CarService.java
│   │           └── util
│   │               └── HibernateUtils.java
│   └── resources
│       └── hibernate.cfg.xml
└── test
    └── java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>HibernateDerbyEx</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>13</maven.compiler.source>
        <maven.compiler.target>13</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.15.2.0</version>
        </dependency>


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

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>

</project>

In the pom.xml file, we define two dependencies: the hibernate-core libraries and the derbyclient driver. In the <build> element, we let the build system include XML files — we are going to place XML mapping files into the src/main/java directory.

src/main/java/resources/hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.username">app</property>
        <property name="hibernate.connection.password">app</property>
        <property name="hibernate.connection.url">jdbc:derby://localhost:1527/testdb</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <property name="hibernate.dialect">org.hibernate.dialect.DerbyTenSevenDialect</property>
        <mapping resource="com/zetcode/hibernate/Car.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

In the Hibernate configuration file, we provide the connection properties to the Derby database. We enable Hibernate's automatic session context management and specify a Derby SQL dialect. The mappings are added with the <mapping> element. We have one mapping — of a Car object to the cars table.

com/zetcode/bean/Car.java
package com.zetcode.bean;

import java.util.Objects;

public class Car {

    private Long Id;
    private String Name;
    private Integer Price;

    public Long getId() {
        return Id;
    }

    public void setId(Long Id) {
        this.Id = Id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String Name) {
        this.Name = Name;
    }

    public Integer getPrice() {
        return Price;
    }

    public void setPrice(Integer Price) {
        this.Price = Price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return Objects.equals(Id, car.Id) &&
                Objects.equals(Name, car.Name) &&
                Objects.equals(Price, car.Price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(Id, Name, Price);
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Car{");
        sb.append("Id=").append(Id);
        sb.append(", Name='").append(Name).append('\'');
        sb.append(", Price=").append(Price);
        sb.append('}');
        return sb.toString();
    }
}

This is a Car bean. It has three attributes and corresponding getters and setters.


com/zetcode/hibernate/Car.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zetcode.bean.Car" table="cars" catalog="app">
        <id name="Id" type="java.lang.Long">
            <column name="Id" />
            <generator class="identity" />
        </id>
        <property name="Name" type="string">
            <column name="Name" length="30"/>
        </property>
        <property name="Price" type="integer">
            <column name="Price" />
        </property>
    </class>
</hibernate-mapping>

In the Car.hbm.xml file, we provide the mapping between the Car class and the CARS table. We map the attributes of the class to the columns of the database table. The mapping is specified between the <hibernate-mapping> and </hibernate-mapping> elements.

<generator class="identity" />

The generator element informs Hibernate what strategy is used to generate primary keys. The identity generator class allows an integer/bigint column to be auto-incremented on demand. This generator is supported by Derby.

com/zetcode/util/HibernateUtils.java
package com.zetcode.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {

    private HibernateUtils() {}

    private static final SessionFactory sessionFactory;

    static {
        try {
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

   public static void shutdown() {

        getSessionFactory().close();
    }
}

The HibernateUtils is a helper class which handles startup and accesses SessionFactory to obtain a session object. The session object is then used to access the database.

sessionFactory = new Configuration().configure().buildSessionFactory();

This line creates a SessionFactory from the hibernate.cfg.xml file.

getSessionFactory().close();

This line closes caches and connection pools.

com/zetcode/service/CarService.java
package com.zetcode.service;

import com.zetcode.bean.Car;
import com.zetcode.util.HibernateUtils;
import java.util.List;
import org.hibernate.Session;

public class CarService {

    private CarService() {};

    public static Car getCarById(Long id) {

        Car car;
        try (Session session = HibernateUtils.getSessionFactory().openSession()) {
            car = session.get(Car.class, id);
        }

        return car;
    }

    @SuppressWarnings("unchecked")
    public static List<Car> getCars() {

        List<Car> cars;
        try (Session session = HibernateUtils.getSessionFactory().openSession()) {
            cars = session.createQuery("from Car").list();
        }
        return cars;
    }

    public static void save(Car car) {

        try (Session session = HibernateUtils.getSessionFactory().openSession()) {
            session.beginTransaction();

            session.save(car);

            session.getTransaction().commit();
        }
    }
}

In the CarService class we have service methods to obtain a car by its ID, get all cars, and save a new car.

try (Session session = HibernateUtils.getSessionFactory().openSession()) {
    car = session.get(Car.class, id);
}

The HibernateUtils is used to obtain and open a session object. The Session's get() method returns the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.

cars = session.createQuery("from Car").list();

The createQuery method creates a new instance of Query for the given HQL query string. The from Car query returns all instances of the Car class.

session.save(car);

The save method persists the given instance.

com/zetcode/main/HibernateDerbyEx.java
package com.zetcode.main;

import com.zetcode.bean.Car;
import com.zetcode.service.CarService;
import com.zetcode.util.HibernateUtils;
import java.util.List;

public class HibernateDerbyEx {

    public static void main(String[] args) {

        Long id = 1L;

        Car car = CarService.getCarById(id);

        System.out.println(car);

        Car newCar = new Car();

        newCar.setName("Toyota");
        newCar.setPrice(34500);

        CarService.save(newCar);

        List<Car> cars = CarService.getCars();

        for (Car mycar : cars) {

            System.out.println(mycar);
        }

        HibernateUtils.shutdown();
    }
}

This is the main application class. We get a car by its ID, save a new car, and list all cars from the database table.

Long id = 1L;

Car car = CarService.getCarById(id);

We use a CarService's getCarById() method to retrieve a car by its ID.

Car newCar = new Car();

newCar.setName("Toyota");
newCar.setPrice(34500);

CarService.save(newCar);

A new car is created and saved into the database.

List<Car> cars = CarService.getCars();

for (Car mycar : cars) {

    System.out.println(mycar);
}

We list all cars from the cars table.

HibernateUtils.shutdown();

In the end, we close opened resources.

Derby with native Hibernate API and annotation mapping

In this section, we create a Java console application that performs some database tasks on a Derby database. We use the Hibernate native API and annotation mapping.

The pom.xml, CarService.java, HibernateDerbyEx.java, HibernateUtils.java files do not change. The hibernate.cfg.xml and Car.java do change.

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

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.username">app</property>
        <property name="hibernate.connection.password">ap</property>
        <property name="hibernate.connection.url">jdbc:derby://localhost:1527/testdb</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <property name="hibernate.dialect">org.hibernate.dialect.DerbyTenSevenDialect</property>
        <mapping class="com.zetcode.bean.Car"></mapping>
    </session-factory>
</hibernate-configuration>

In the hibernate.cfg.xml file, the <mapping> element has changed.

<mapping class="com.zetcode.bean.Car"></mapping>

We use a class attribute to point to the Java Entity, which contains the mapping annotations.

com/zetcode/bean/Car.java
package com.zetcode.bean;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Table;
import javax.persistence.Id;
import java.util.Objects;

@Entity
@Table(name="cars")
public class Car {

    private Long Id;
    private String Name;
    private Integer Price;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return Id;
    }

    public void setId(Long Id) {
        this.Id = Id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String Name) {
        this.Name = Name;
    }

    public Integer getPrice() {
        return Price;
    }

    public void setPrice(Integer Price) {
        this.Price = Price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return Objects.equals(Id, car.Id) &&
                Objects.equals(Name, car.Name) &&
                Objects.equals(Price, car.Price);
    }

    @Override
    public int hashCode() {
        return Objects.hash(Id, Name, Price);
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Car{");
        sb.append("Id=").append(Id);
        sb.append(", Name='").append(Name).append('\'');
        sb.append(", Price=").append(Price);
        sb.append('}');
        return sb.toString();
    }
}

In the Car.java class, we define the mappings with the annotations. The names of the class attributes and the names of the table columns are automatically paired. If the names were different, we would have to specify the column names with the @Column annotation.

@Entity
@Table(name="cars")
public class Car implements Serializable {

The class is decorated with the @Entity annotation; the @Table annotation specifies the primary table for the annotated entity.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {

The @Id annotation specifies the primary key of an entity and the @GeneratedValue provides for the specification of generation strategies for the values of primary keys.

In this tutorial, we have presented the Hibernate ORM. We have used the Derby database.