Hibernate学习笔记

1. Java链接数据库

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
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

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

public class JdbcMain {
public static void main(String[] args) throws ClassNotFoundException {
// TODO: Load the SQLite JDBC driver (JDBC class implements java.sql.Driver)
Class.forName("org.sqlite.JDBC");
// TODO: Create a DB connection
try(Connection connection = DriverManager.getConnection("jdbc:sqlite:contactmgr.db")) {

// TODO: Create a SQL statement
Statement statement = connection.createStatement();

// TODO: Create a DB table
statement.executeUpdate("DROP TABLE IF EXISTS contacts");
statement.executeUpdate("CREATE TABLE contacts (id INTEGER PRIMARY KEY, firstname STRING, lastname STRING, email STRING, phone INT(10))");

// TODO: Insert a couple contacts
statement.executeUpdate("INSERT INTO contacts (firstname, lastname, email, phone) VALUES('Liu', 'Lixiang', 'liulixiang1988@gmail.com', 1234567890)");
statement.executeUpdate("INSERT INTO contacts (firstname, lastname, email, phone) VALUES('Long', 'Long', 'abc@gmail.com', 0987654321)");

// TODO: Fetch all the records from the contacts table
ResultSet rs = statement.executeQuery("SELECT * FROM contacts");

// TODO: Iterate over the ResultSet & display contact info
while(rs.next()){
int id = rs.getInt("id");
String firstName = rs.getString("firstname");
String lastName = rs.getString("lastname");

System.out.printf("%s %s (%d)", firstName, lastName, id);
}

} catch (SQLException ex) {
// Display connection or query errors
System.err.printf("There was a database error: %s%n",ex.getMessage());
}
}
}

编译:javac JdbcMain.java

运行:java -cp sqlite-jdbc.3.8.6.jar:. JdbcMain

2 Hibernate入门

2.1 创建一个使用Hibernate的项目

创建gradle项目contactmgr-hibernate项目,并修改build.gradle:

1
2
3
4
dependencies {
compile 'org.hibernate:hibernate-core:5.1.0.Final'
compile 'com.h2database:h2:1.4.191'
}

在根目录创建data文件夹,用来存放h2文件数据库。

resources目录下创建hibernate.cfg.xml,这个文件用来保存SessionFactory的配置:

1
2
3
4
5
6
7
8
9
<hibernate-configuration>
<session-factory>
<!--数据库链接配置-->
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:./data/contactmgr</property>
<!--SQL 方言-->
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
</session-factory>
</hibernate-configuration>

2.2 使用JPA注解添加POJO

添加包io.github.liulixiang1988.contactmgr,并在其中创建Application类:

1
2
3
4
5
6
7
package io.github.liulixiang1988.contactmgr;

public class Application {
public static void main(String[] args) {

}
}

然后在contactmgr中创建model包,并创建Contact类:

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package io.github.liulixiang1988.contactmgr.model;

import javax.persistence.*;

@Entity //映射为表
public class Contact {

@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //自增长
private int id;

@Column
private String firstName;

@Column
private String lastName;

@Column
private String email;

@Column
private Long phone;

// 为JPA准备的
public Contact(){}

@Override
public String toString() {
return "Contact{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", phone=" + phone +
'}';
}

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 getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Long getPhone() {
return phone;
}

public void setPhone(Long phone) {
this.phone = phone;
}
}

然后我们修改hibernate.cfg.xml来为model做一些配置:

1
2
3
4
5
6
7
8
9
10
<hibernate-configuration>
<session-factory>
<!--...-->
<!--启动时创建数据结构-->
<property name="hbm2ddl.auto">create</property>

<!--为标识的实体类命名-->
<mapping class="io.github.liulixiang1988.contactmgr.model.Contact"/>
</session-factory>
</hibernate-configuration>

2.3 创建Hibernate SessionFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Application {
//保存一个SessionFactory(我们也只需要一个)
private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
//创建StandardServiceRegistry
final ServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
return new MetadataSources(registry).buildMetadata().buildSessionFactory();
}

public static void main(String[] args) {

}
}

2.4 Builder模式

修改Contact.java

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
public class Contact {

//...

@Override
public String toString() {
return "Contact{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", phone=" + phone +
'}';
}

//...

public static class ContactBuilder {
private String firstName;
private String lastName;
private String email;
private Long phone;

public ContactBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public ContactBuilder withEmail(String email) {
this.email = email;
return this;
}

public ContactBuilder withPhone(Long phone) {
this.phone = phone;
return this;
}

public Contact build() {
return new Contact(this);
}
}
}

修改Application.java:

1
2
3
4
5
6
public static void main(String[] args) {
Contact contact = new ContactBuilder("Chris","Ramacciotti")
.withEmail("rama@teamtreehouse.com")
.withPhone(7735556666L)
.build();
}

3. 使用Hibernate存取数据

要让Hibernate支持存取数据,需要添加依赖:

1
compile 'javax.transaction:jta:1.1'

为了能看到Hibernate准备的查询,我们设置:

1
<property name="show_sql">true</property>

3.1 添加数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
Contact contact = new ContactBuilder("Chris","Ramacciotti")
.withEmail("rama@teamtreehouse.com")
.withPhone(7735556666L)
.build();

//打开session
Session session = sessionFactory.openSession();

//begin transaction
session.beginTransaction();

//使用session来保存对象
session.save(contact);

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

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

3.2 查询数据

1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings("unchecked")
private static List<Contact> fetchAllContact() {
Session session = sessionFactory.openSession();
//创建Criteria
Criteria criteria = session.createCriteria(Contact.class);

//从Criteria中获取数据
List<Contact> contacts = criteria.list();

//关闭会话
session.close();
return contacts;
}

调用可以使用java8的特性,而非使用for循环:

1
fetchAllContact().stream().forEach(System.out::println);

可以通过修改hibernate.cfg.xml,让每次启动时是更新而不是创建数据库:

1
<property name="hbm2ddl.auto">update</property>

3.3 更新与删除

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
private static Contact findContactById(int id) {
//打开会话
Session session = sessionFactory.openSession();
//获取对象或者null
Contact contact = session.get(Contact.class, id);
//关闭会话
session.close();
//返回对象
return contact;
}

private static void update(Contact contact) {
Session session = sessionFactory.openSession();
session.beginTransaction();
session.update(contact);
session.getTransaction().commit();
session.close();
}

private static void delete(Contact contact) {
Session session = sessionFactory.openSession();
session.beginTransaction();
session.delete(contact);
session.getTransaction().commit();
session.close();
}