Merikanto

一簫一劍平生意,負盡狂名十五年

Configuring & Testing Hibernate

Hibernate is an Object Relational Mapping (ORM) tool for Java. It provides a framework for mapping an object-oriented domain model to a relational database, such as MySQL.


Configuration


Note: The mapping used here avoids using annotations in the Java class.

Instead, we will create a mapping file for the class object, under the same package.


The project structure under src/main/java/merikanto is below :

1
2
3
4
5
6
7
HelloHibernate/src/main/java/merikanto
└── hibernate
├── entity
│ ├── User.hbm.xml
│ └── User.java
└── test
└── Test.java

To start with, we first set the configs below in MySQL:

1
2
3
> create database hibernate;

> SET GLOBAL time_zone = '-4:00'; -- Necessary, otherwise serverTimeZone error.

Then create a Maven project in terminal:

1
2
3
4
mvn archetype:generate \
-DgroupId=merikanto.hibernate \
-DartifactId=HelloHibernate \
-DarchetypeArtifactId=maven-archetype-quickstart

Open the project in Intellij, and make sure that the database is connected (Need MySQL connector).

Project structure - Libraries - search mysql - connect

View - Tool windows - database - add data source - mysql


Next, edit pom.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?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>merikanto.hibernate</groupId>
<artifactId>HelloHibernate</artifactId>
<version>1.0-SNAPSHOT</version>

<name>HelloHibernate</name>
<url>https://merikanto.github.io</url>

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

<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.11.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
</dependencies>

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

<plugins>
<plugin>
<groupId>merikanto.hibernate</groupId>
<artifactId>HelloHibernate</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<classpathScope>test</classpathScope>
<!--Changing the classpath scope!! -->
<mainClass>Test</mainClass>
</configuration>
</plugin>
</plugins>
</build>

</project>

Create package entity under merikanto.hibernate, then create new object (class) User under entity.

A user has 3 properties:

  • id
  • username
  • password
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package merikanto.hibernate.entity;

public class User {

private int id;
private String username;
private String password;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

Then create User.hbm.xml, under the same entity package as User class.

This file is for mapping (One object – One mapping file).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0"?>

<!-- 映射对应的 package -->
<hibernate-mapping package="merikanto.hibernate.entity">

<!-- 实体类和数据库中的表对应(如果没有这个表则新建) -->
<class name="User" table="user_info">

<!-- id 主键 和其他属性对应表中相应的字段(这些都是在 User.java 实体类中定义的) -->
<id name="id" column="user_id"/>
<property name="username" column="user_username"></property>
<property name="password" column="user_password"></property>

</class>
</hibernate-mapping>

Under src/main/java, create Hibernate configuration file hibernate.cfg.xml .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version='1.0' encoding='utf-8'?>

<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->

<!-- 表示使用 mysql 数据库驱动类 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- jdbc 的连接 url 和数据库(使用我们之前新建的 hibernate)-->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>

<!-- 数据库用户名 -->
<property name="connection.username">root</property>

<!-- 密码(我的密码为空) -->
<property name="connection.password"></property>

<!-- JDBC connection pool (use the built-in) 这一行注释掉-->
<!-- <property name="connection.pool_size">1</property>-->

<property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>

<!-- Echo all executed SQL to stdout -->
<!-- 设置 打印输出 sql 语句 为真 -->
<property name="show_sql">true</property>

<!-- 设置格式为 sql -->
<property name="format_sql">true</property>

<!-- 第一次加载 hibernate 时根据实体类自动建立表结构,以后自动更新表结构 -->
<property name="hbm2ddl.auto">update</property>

<!-- 映射文件 -->
<mapping resource="merikanto/hibernate/entity/User.hbm.xml"/>

</session-factory>

</hibernate-configuration>

And now the configuration is done.


Test (CRUD)

Now we run some tests for hibernate. There will be four tests, focusing on the operations below:

  • Create
  • Read (search)
  • Update
  • Delete

Create

First we create package test under merikanto.hibernate, then we create class Test under merikanto.hibernate.test.

The first test is for the Create operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package merikanto.hibernate.test;

import merikanto.hibernate.entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;


public class Test {

public static void main(String[] args) {

// 获取 Hibernate 配置信息
Configuration configuration = new Configuration().configure();
@SuppressWarnings("deprecation")

// 根据 configuration 建立 sessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();

// 开启 session(相当于开启 JDBC 的 connection)
Session session = sessionFactory.openSession();

// 创建并开启事务对象
session.beginTransaction();

// 新建对象,并赋值
User user = new User();
user.setId(1);
user.setUsername("admin");
user.setPassword("admin");

// 保存对象
session.save(user);

// 提交事务
session.getTransaction().commit();

// 关闭 session 和 sessionFactory
session.close();
sessionFactory.close();
}
}

Then run it in Terminal:

1
2
mvn compile
mvn exec:java -Dexec.mainClass="merikanto.hibernate.test.Test"

Read

The second test is for the Read operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package merikanto.hibernate.test;

import merikanto.hibernate.entity.User;
import java.util.List;

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


public class Test {

public static void main(String[] args) {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
//如果不写配置文件名就会使用默认配置文件名 hibernate.cfg.xml
.configure("hibernate.cfg.xml")
.build();

// 建立 sessionFactory
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();

Session session = sessionFactory.openSession();
session.beginTransaction();

// 利用 StringBuilder 来连接查询语句
StringBuilder hq = new StringBuilder();

// 从 User 里面查找(注意 from 后有空格)
// 相当于 "select * from user_info;"
hq.append("from ").append( User.class.getName() );

// 利用 session 建立 query
Query query = session.createQuery( hq.toString() );

// 序列化 query 的结果为一个 list 集合
List<User> users = query.list();

// 打印每一个 User 信息(这里只打印了名字,你也可以打印其他信息)
for (User user : users) {
System.out.println( user.getUsername() );

}

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

Then run it in Terminal:

1
2
mvn compile
mvn exec:java -Dexec.mainClass="merikanto.hibernate.test.Test"

Update

The third test is for the Update operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package merikanto.hibernate.test;

import merikanto.hibernate.entity.User;
import java.util.List;

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


public class Test {

public static void main(String[] args) {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
//如果不写配置文件名就会使用默认配置文件名 hibernate.cfg.xml
.configure("hibernate.cfg.xml")
.build();
// 建立 sessionFactory
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();

Session session = sessionFactory.openSession();
session.beginTransaction();

StringBuilder hq = new StringBuilder();

// 对比查找的操作来看,因为我们需要修改指定 name 的用户密码,后面需要再添加查询条件
// 注意 from、where 的空格,":name" 表示一个参数
hq.append("from ").append(User.class.getName()).append(" where user_username=:name");

Query query = session.createQuery(hq.toString());

// 这里就设定参数 name 的值为"user1"
query.setParameter("name","user1" );

List<User> users = query.list();

for (User user : users) {

// 修改 user1 的密码
user.setPassword("123-user");

// 注意这里是 update
session.update(user);
}

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

Then run it in Terminal:

1
2
mvn compile
mvn exec:java -Dexec.mainClass="merikanto.hibernate.test.Test"

Delete

The fourth test is for the Delete operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package merikanto.test.hibernate.test;

import merikanto.hibernate.entity.User;
import java.util.List;

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


public class Test {

public static void main(String[] args) {
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
//如果不写配置文件名就会使用默认配置文件名 hibernate.cfg.xml
.configure("hibernate.cfg.xml")
.build();
// 建立 sessionFactory
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();

Session session = sessionFactory.openSession();
session.beginTransaction();

StringBuilder hq = new StringBuilder();

// 对比查找时候的操作来看,因为我们需要修改指定 name 的用户密码,后面需要再添加查询条件
// 注意 from、where 的空格,":name" 表示一个参数
hq.append("from ").append(User.class.getName()).append(" where user_username=:name");

Query query = session.createQuery(hq.toString());

// 这里就设定参数 name 的值为"user1"
query.setParameter("name", "user1");

List<User> users = query.list();

for (User user : users) {
// 注意这里是 delete
session.delete(user);
}

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

Then run it in Terminal:

1
2
mvn compile
mvn exec:java -Dexec.mainClass="merikanto.hibernate.test.Test"

And we now have implemented the tests.