Hibernate的使用

以及一些玄学注意事项

Posted by Donggu Ho on 2016-11-30

一切能自动生成代码的东西都是程序猿的好朋友!

不知道为什么自动生成的部分语句以及网上的教程都有报错的地方,于是翻了翻官方文档。

在 IntelliJ IDEA 中配置使用 Hibernate

IDE: IntelliJ IDEA 2016.2.5
Hibernate: Hibernate 5.3
目标: 配置 Hibernate 使其通过 JDBC 连接到 MySQL 数据库

添加数据源

  • 双击Shift,在万能搜索框中输入database,打开数据库管理Tool Window
  • 在选项卡中戳+添加 MySQL 数据源
  • 填写各种信息;假如显示没有 driver 的话可以直接点 download 自动下载。假如是已经下载过 JDBC 需要导入包。
    导入了 driver 之后 test connection 按钮就可以按了,假如连接成功就可以按确定保存。
  • 然后右侧的窗口就会出现数据库及其 schema,双击表格可以查看表格信息,也可以修改什么的。也可以打开 console 执行SQL语句,一切操作和 Jetbrains DataGrip 一毛一样。吓得我把 DataGrip 卸了。

加入 Hibernate 支持并生成实体类

  • 右击目标 Model,选择 Add Framework Surpport…。也可以直接新建一个 Model。
  • 左边勾选 Hibernate,在右侧上面两个选项也都勾选。
    假如未下载 Hibernate 包的话选 download 即可,可以在 configure… 中设置下载路径;假如已经有的话选择 Use library,戳 Create 然后选中 Hibernate 的全部.jar文件即可。

    假如是新建 Model 的话,Hibernate 位于 Java Enterprise 的子项中。
  • 按确定后,会出现导入 Schema 的界面。选择目标数据源和实体类文件的存放 Package ,在中间的框内勾选要导入的表。
    在下面的生成选项中,选择如图。选择 JPA Mapping Descripter, 在弹出窗口中选择合适路径新建一个.xml文件。勾选最下面一行。点OK开始生成。
  • Hibernate 会在目标 Package 中生成对应表的实体类,以及在模块下生成一个配置文件hibernate.cfg.xml和一个简单的main.java文件,还有一个mapping XML,这样首次的生成就完成了。
  • 在后面的过程中想要继续添加的话,双击Shift,输入Persitence打开相应的窗口,右击目标 Hibernate 模块,选择 Generate Persistence Mapping | By Database Schema 就可以打开导入的窗口。

Hibernate 的使用

  • 首先需要修改hibernate.cfg.xml,在其中加入连接数据库的用户名和密码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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="connection.url">jdbc:mysql://10.60.42.203:8888/DB_02</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- 加入这两行 -->
<property name="connection.username">****</property>
<property name="connection.password">********</property>

<mapping class="Model.User"/>
<mapping class="Model.Achievement"/>
<mapping class="Model.AchievementUser"/>
<mapping class="Model.Record"/>
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>

每次导入新的表后这个配置文件也会自动更新,但这两行也会自动消失……我觉得我应该研究一下如何修改 IDEA 的文件模板了……

  • Main.java其实提供了简单的试运行函数语句,但是大概是模板有点过时……总之部分语句已经不能用了。我大概根据官方文档重写了一个HibernateDemo.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
46
47
48
49
50
51
52
53
54
55
import org.hibernate.*;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

/**
* Created by Donggu on 2016/11/29.
*/
public class HibernateDemo {
private SessionFactory factory;

protected void init() throws Exception {
// A SessionFactory is set up once for an application!
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // configures settings from hibernate.cfg.xml
.build();
try {
this.factory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
System.out.println("hello");
}
catch (Exception e) {
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
// so destroy it manually.
StandardServiceRegistryBuilder.destroy( registry );
e.printStackTrace();
}
}

public Session getSession() throws HibernateException {
return factory.openSession();
}

void doSomething(){
Session session = getSession();
Transaction tx = null;
try{
tx = session.beginTransaction();

// do somthing...

tx.commit();
}catch (HibernateError e){
e.printStackTrace();
}finally {
if(tx!=null)tx.rollback();
session.close();
}
}

public static void main(String[] args) throws Exception{
HibernateDemo test = new HibernateDemo();
test.init();
test.doSomething();
}
}
  • doSomething里面是跟数据库相关的执行内容。比如需要列出所有 User 的名字:
1
2
3
4
5
List users = session.createQuery("from User").list();
for(Iterator it = users.iterator(); it.hasNext();){
User user = (User) it.next();
System.out.println(user.getUsername());
}

玄学报错的玄学处理

expecting idClass mapping

java.lang.IllegalArgumentException: expecting IdClass mapping

idclass是表有联合主键(Primary Key 有多于一个 Attibute)时会出现的东西。如果在生成实体类时选了 Hibernate Mapping 生成了相关的.xml文件,文件中的<composite-id>会对解析造成干扰【并不知道为什么【所以是玄学
把额外生成的xml全部删掉即可(hibernate.cfg.xml 中相关的描述也要删掉)。但是生成的时候选择的是 JPA Mapping Descripter 的话不能删掉额外生成的 .xml 文件。这个差异来自于生成时选择的不同会在实体类中加入不同的 JPA Annotation。

啊 神奇的玄学