一个框架的学习不到第二遍我是不敢写文章的,我总是跟着不同的视频做不同的学习,我个人认为这样可以更好的巩固知识点。已经是hibernate学习的二周目了,所以有了新的感悟,也有了新的问题要和大家分享。目前2017/06/04的hibernate版本是5.2.10,我当前使用的版本是5.2.8。现在主流的教程使用的版本都是4.x.x的版本╮(╯▽╰)╭。
昨天复习了MyBatis的知识,写了几篇文章,今日再来看hibernate,感受到的是两个ORM框架在设计思维和目的上的不同。但是更多的是真的感受到了智慧的火花。好了,废话不多说,开始体验一把hibernate。
既然是对象到关系的映射,我们需要先有一个对象。
public class News {
private int id;
private String title;
private String author;
private Date date;
public News() {
}
public News(String title, String author, Date date) {
this.title = title;
this.author = author;
this.date = date;
}
// 省略了set/get/toString方法
}
好了,到目前为止,接触了那么多的框架,如果要想让框架融入我们的项目,总是需要一个核心配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate1</property>
<property name="hibernate.connection.username">root</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 是否在控制台打印SQL语句 -->
<property name="show_sql">true</property>
<!-- 打印的SQL语句是否需要格式化 -->
<property name="format_sql">true</property>
<!-- 可以帮助java代码生成数据库脚本,进而生成具体的表结构 -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="edu/ctgu/hibernate/news/News.hbm.xml"/>
</session-factory>
</hibernate-configuration>
下面的工作就是将Java对象映射到数据库关系(数据表),所以需要一个映射文件。这点和MyBatis有点不同,因为在hibernate中完全不需要SQL语句的构建,框架自动就做了,开发者完全面向对象操作即可。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="edu.ctgu.hibernate.news.News" table="NEWS">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
<property name="title" type="java.lang.String">
<column name="TITLE" />
</property>
<property name="author" type="java.lang.String">
<column name="AUTHOR" />
</property>
<property name="date" type="java.sql.Date">
<column name="DATE" />
</property>
</class>
</hibernate-mapping>
好了,配置工作基本完成,单元测试可以做了。
public class NewsTest {
private SessionFactory factory = null;
private Session session = null;
private Transaction transaction = null;
@Before
public void testBefore(){
// 1.初始化配置文件加载配置信息,默认加载src目录下的hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
// 3.初始化SessionFactory,别忘了之前重要的注册
factory = configuration.buildSessionFactory();
// 4.打开Session
session = factory.openSession();
// 5.开启事务
transaction = session.beginTransaction();
}
@After
public void testAfter(){
transaction.commit();
session.close();
factory.close();
}
@Test
public void test(){
News news = new News("今日头条", "雷军", new Date(new java.util.Date().getTime()));
session.save(news);
}
}
这里有一个不得不提出的问题,一个折腾了我两个小时的问题。在hibernate更新到版本4的时候,出现了一个新特性,需要注册配置和服务,所以4.x.x是这样得到SessionFactory的:
Configuration config = new Configuration().configure("abc.xml");
ServiceRegistry seRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
SessionFactory sf = config.buildSessionFactory(seRegistry);
但是版本5不支持这样创建了啊,但是可以支持这样写:
// 1.初始化配置文件加载配置信息,默认加载src目录下的hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
// 2.将配置信息注册到服务中
ServiceRegistry registry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
// 3.初始化SessionFactory,别忘了之前重要的注册
SessionFactory factory = configuration.buildSessionFactory(registry);
预编译不会报错,语法语义都没问题,但是一跑起来就会出现UnKnown Entity的异常,简直气死人。
终于,我看到了一个大牛的博客,人家也有这样的困扰,访问了老外的网站(其实我完全可以先去看看hibernate的官方demo,奈何吃了英语的亏╮(╯▽╰)╭)。然后给出了两种方法,比较稳定的一种就是我当前使用的。我不知道hibernate3是不是就是这样写的,因为注册配置和服务是版本4新增的。唉,这些都无从考证了,只是希望新入坑的朋友少吃亏。