In this article, we will learn how to configure Hibernate in our Java project with Maven. There are some problems when doing with Hibernate, and we will solve them to know more about configuration in Hibernate.
Let’s get started.
Table of content
- Creating project using Maven
- Preparing database in MySQL
- Add dependencies of Maven to pom.xml file
- Configuring xml file for Hibernate
- Creating entity that is corresponding to a table in MySQL
- Creating CRUD operations to MySQL
- Fix some problems
- Wrapping up
Creating project using Maven
Belows are some steps that we need to create project with Maven:
So, after passing all above steps, we have a project that is managed by Maven. When we want to add libraries, we can fill in pom.xml
file.
Finally, we will have the structure of Maven project like the below image:
Preparing database in MySQL
In order to implement the communication between MySQL and Hibernate, we need to create our own database in MySQL. The following is the content of sql file that is used to create database and table Employee
.
CREATE DATABASE java_sql;
USE java_sql;
CREATE TABLE `EMPLOYEE` (
ID INT NOT NULL AUTO_INCREMENT,
FULL_NAME VARCHAR(20) DEFAULT NULL,
AGE INT DEFAULT NULL,
PRIMARY KEY (ID)
);
INSERT INTO `employee` (ID, FULL_NAME, AGE)
VALUES
(1, "John", 56),
(2, "Bill Adam", 45),
(3, "Mary Smith", 78);
SELECT * FROM `employee`;
Add dependencies of Maven to pom.xml file
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.0-GA</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
Configuring xml file for Hibernate
All information about configurations of Hibernate is contained in a standard Java properties file called hibernate.properties
, or an XML file named hibernate.cfg.xml
.
In this article, we will use the hibernate.cfg.xml
file. It is located in src/main/resouces
folder.
The content of hibernate.cfg.xml
file like that:
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/java_sql</property>
<property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">12345</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<mapping class="com.mhb.manhpd.hibernate.Employee"/>
</session-factory>
</hibernate-configuration>
In MySQL, we should note that when we remove two properties such as hibernate.connection.useUnicode
, and hibernate.connection.characterEncoding
. In Eclipse, we have an error like Exception in thread main org.hibernate.exception.JDBCConnectionException: Error calling Driver#connect
.
When we find DDL for employee
table, we have:
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Therefore, in our table, it uses charset that is utf8mb4 - UTF8 Unicode. In order that hibernate can communicate with MySQL succesfully, we have to set value for hibernate.connection.useUnicode
is true
, and set value for hibernate.connection.characterEncoding
is UTF-8
.
To show the MySQL default character set, we have to login to the MySQL console and execute SHOW VARIABLES LIKE 'char%';
.
If we want to change it, for example, to utf8, we have to add this:
default-character-set = utf8
to the client, mysqld_safe
, mysqld
and mysqldump
section (may differ depending on configuration) in your my.cnf and restart the mysql daemon.
We can go to this link to refer some information about configuration in Hibernate.
When we want to connect with the other RDBMSs, we will have some values of hibernate.dialect
, hibernate.connection.driver_class
, and hibernate.connection.url
.
-
MySQL
<property name="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/database_name</property>
-
Oracle
<property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property> <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521/database_name</property>
-
PostgreSQL
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL95Dialect</property> <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/database_name</property>
-
SQL Server
<property name="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</property> <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> <property name="hibernate.connection.url">jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=java_sql</property>
-
MariaDB
<property name="hibernate.dialect">org.hibernate.dialect.MariaDB53Dialect</property> <property name="hibernate.connection.driver_class">org.mariadb.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mariadb://127.0.0.1:port_number/java_sql</property>
Creating entity that is corresponding to a table in MySQL
We will generate entity that is mapped to data types of employee
table in MySQL.
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "employee")
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "FULL_NAME")
private String name;
@Column(name = "AGE")
private int age;
public Employee() {
// nothing to do
}
public Employee(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Employee: " + this.id + ", " + this.name + ", " + this.age;
}
}
We have some rules for persistent class that we can apply to our own cases.
-
All Java classes that will be persisted need a default constructor.
-
All classes should contain an ID in order to allow easy identification of our objects within Hibernate and the database. This property maps to the primary key column of a database table.
-
All attributes that will be persisted should be declared private and have
getXXX()
andsetXXX()
methods defined in the JavaBean style. -
A central feature of Hibernate, proxies, depends upon the peristent class being either non-final, or the implementation of an interface that declares all public methods.
-
All classes that do not extend or implement some specialized classes and interface required by the EJB framework.
Creating CRUD operations to MySQL
Fix some problems
-
If we modify Hibernate from EclipseLink, with one-to-one relationship or one-to-many relationship, we have error such as:
Multiple writable mappings exist for the field []. Only one may be defined as writable, all others must be specified read-only.
Source code for this problem:
public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private int id; private String email; private String password; private int reputation; @OneToOne(mappedBy="user", cascade={CascadeType.ALL}) private Company company; @OneToOne(mappedBy="user") private Person person; ... } @Entity public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="id_user") private int idUser; @Temporal( TemporalType.DATE) private Date birthdate; private String gender; private String name; private String surname; @OneToOne @JoinColumn(name="id_user", insertable=false, updatable=false) private User user; } public class Company implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="id_user") private int idUser; private String email; private String name; @ManyToOne @JoinColumn(name="area") private Area areaBean; @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name="id_user", insertable=false, updatable=false) private User user; }
The reason for this error: we have the
id_user
column mapped twice, once using a basic@Id
mapping, and once using the@ManyToOne
. We need to make one of them readonly, such asinsertable=false
,updatable=false
in@JoinColumn
annotation. Or better just remove the basic id, and put the@Id
on the@ManyToOne
.So, we have two way to solve this error:
- Replace
@JoinColumn(name="area")
as@PrimaryKeyColumn(name = "area", referencedColumnName = "id")
. - Placing the
insertable=false
,updatable=false
in the@JoinColumn
annotation in both classes,Person
andCompany
.
We can reference to this link.
- Replace
Wrapping up
Refer:
https://examples.javacodegeeks.com/enterprise-java/hibernate/hibernate-annotations-example/
https://stackoverflow.com/questions/44248528/what-is-the-maven-dependency-for-java-ee7-and-cdi-2-0
https://www.baeldung.com/ejb-session-beans
https://dzone.com/articles/in-practice-dependency-injection-with-java-ee
https://stackoverflow.com/questions/7297565/javassist-what-is-the-main-idea-and-where-real-use
Problem about encoding in database
https://makandracards.com/makandra/2529-show-and-change-mysql-default-character-set
https://vladmihalcea.com/jdbc-driver-connection-url-strings/