Hibernate项目配置
作为一个优秀的持久层框架Hibernate很容易入门。在使用Hibernate框架前,先来看看Hibernate是如何实现ORM框架的,即Hibernate的执行流程,如图所示:
现在开始新建我们的第一个Hibernate项目
1.在Eclipse中创建Web项目,名称为HibernateConfigure
2. 将下载下来的Hibernate框架E:\hibernate-release-5.2.9.Final\lib\required
中的jar包复制粘贴到WEB-INF\lib
目录下
3.把数据库驱动包复制粘贴到WEB-INF\lib
目录下(比如我的是Oracle数据库,版本为11g,驱动jar包为ojdbc,MySQL数据库则用mysql-connector-java)
4.创建实体类。在src目录下新建com.skt.entity
包,并在其中创建实体类UserTest(对应数据库表user_test,没有的话自己新建一个表,字段自己随便设两个)。Users类包含一些属性(对应数据表user_test字段),以及与之对应的getXXX()和setXXX()方法,还包括无参构造方法。
package com.skt.entity;
public class UserTest {
private Integer id;
private String userName;
private String pwd;
private String phone;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public UserTest() {
}
}
5.编写映射文件 UserTest.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-10-14 12:46:14 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.skt.entity.UserTest" table="USER_TEST">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="sequence">
<param name="sequence_name">SEQ_USER_TEST</param>
</generator>
</id>
<property name="userName" type="java.lang.String">
<column name="NAME" />
</property>
<property name="pwd" type="java.lang.String">
<column name="PASSWORD" />
</property>
<property name="phone" type="java.lang.String">
<column name="PHONE" />
</property>
<property name="email" type="java.lang.String">
<column name="EMAIL" />
</property>
</class>
</hibernate-mapping>
6.编写Hibernate配置文件hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
<property name="hibernate.connection.username">MKYDY</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- 运行过程中将sql语句打印出来,建议在开发阶段将其设置为true -->
<property name="show_sql">true</property>
<!-- 根据配置文件更新数据库字段
create:重新建表
create-drop:删除表,再建表
update:更新表
none:不对表操作
-->
<property name="hbm2ddl.auto">none</property>
<mapping resource="com/skt/entity/UserTest.hbm.xml"/>
</session-factory>
</hibernate-configuration>
7. 编写Hbernate工具类HibernateUtil
package com.skt.util;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate工具类
* @author JackerMkydy
*
*/
public class HibernateUtil {
private static SessionFactory sessionFactory;
// 创建线程局部变量threadLocal,用来保存Hibernate的Session
private static final ThreadLocal<Session> threadLocal=new ThreadLocal<Session>();
// 使用静态代码块初始化Hibernate
static
{
try
{
// 读取配置文件
Configuration cfg = new Configuration().configure();
// 创建SessionFactory
sessionFactory = cfg.buildSessionFactory();
}catch(Throwable ex)
{
throw new ExceptionInInitializerError(ex);
}
}
// 获得SessionFactory的实例
public static SessionFactory getsSessionFactory()
{
return sessionFactory;
}
// 获得ThreadLocal对象管理的Session
public static Session getsSession() throws HibernateException
{
Session session=(Session) threadLocal.get();
if(session==null||!session.isOpen())
{
if(sessionFactory==null)
{
rebuildSessionFactory();
}
// 通过SessionFactory对象创建Session对象
session=(sessionFactory!=null)?sessionFactory.openSession():null;
// 将Session对象保存到线程局部变量threadLocal中
threadLocal.set(session);
}
return session;
}
// 关闭Session实例
public static void closeSession()
{
// 从线程局部变量threadLocal中获取之前存入的Session实例
Session session=(Session)threadLocal.get();
threadLocal.set(null);
if(session!=null)
{
session.close();
}
}
// 重建SessionFactory
public static void rebuildSessionFactory()
{
Configuration configuration=new Configuration();
configuration.configure("/hibernate.cfg.xml");
sessionFactory=configuration.buildSessionFactory();
}
// 关闭缓存和连接池
public static void shutdown()
{
getsSessionFactory().close();
}
}
或者
package com.hb.util;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* HibernateUtil 封装session相关内容
* @author oracle
*/
public class HibernateUtil
{
// sessionFactory
private static SessionFactory sessionFactory;
/**
* 获取SessionFactory
* @return SessionFactory
*/
public static SessionFactory getSessionFactory()
{
try
{
// sessionFactory为空时,就重新创建
if (sessionFactory == null)
{
Configuration configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();
}
}
catch (Throwable ex)
{
ex.printStackTrace();
}
return sessionFactory;
}
// 定义session
@SuppressWarnings("rawtypes")
public static final ThreadLocal session = new ThreadLocal();
/**
* 获取当前session
* @return session
*/
@SuppressWarnings("unchecked")
public static Session currentSession()
{
Session s = (Session) session.get();
if (s == null)
{
s = getSessionFactory().openSession();
session.set(s);
}
return s;
}
/**
* 关闭session
* @throws HibernateException 异常
*/
@SuppressWarnings("unchecked")
public static void closeSession() throws HibernateException
{
Session s = (Session) session.get();
session.set(null);
if (s != null)
{
s.close();
}
}
}
8.编写测试类TestUser
package com.skt.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.skt.entity.UserTest;
import com.skt.util.HibernateUtil;
/**
* 测试类,增,删,改,查
* @author oracleOAEC11
*
*/
public class TestUser {
/**
* 添加用户
*/
public void addUser() {
//创建实体类(瞬态对象)
UserTest ut = new UserTest();
ut.setEmail("2384113485@qq.com");
ut.setPhone("1987445345");
ut.setPwd("111111");
ut.setUserName("Tom");
//获得Session对象
Session session = HibernateUtil.getsSession();
//获得Transaction实例
Transaction tc = session.beginTransaction();
try {
// 使用Session的save方法将持久化对象保存到数据库
session.save(ut);
// 提交事务
tc.commit();
} catch (Exception e) {
e.printStackTrace();
// 出现异常,回滚事务
tc.rollback();
}finally {
// 关闭Session连接
HibernateUtil.closeSession();
}
}
/**
* 查找用户
*/
public void getUser() {
UserTest ut = null;
Session session = HibernateUtil.getsSession();
Transaction tx = session.beginTransaction();
try {
// 使用session的get方法获取指定id的用户
ut = session.get(UserTest.class, 2);
System.out.println(ut.getUserName()+":"+ut.getEmail());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
/**
* 删除用户
*/
public void deleteUser() {
Session session = HibernateUtil.getsSession();
Transaction tx = session.beginTransaction();
try {
// 使用session加载一个持久化对象
UserTest ut = session.get(UserTest.class, 3);
session.delete(ut);
System.out.println(ut.getUserName()+":"+ut.getEmail());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
/**
* 更新用户资料
*/
public void updateUser() {
Session session = HibernateUtil.getsSession();
Transaction tx = session.beginTransaction();
try {
// 使用session的update方法更新持久化对象
UserTest ut = session.get(UserTest.class, 2);
ut.setUserName("Alice");
session.update(ut);
tx.commit();
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
} finally {
HibernateUtil.closeSession();
}
}
public static void main(String[] args) {
TestUser tu = new TestUser();
tu.updateUser();
}
}
到此,一个简单的Hibernate项目就搭建完成了。
Hibernate提供了一些常用的主键生成器策略,如下:
- increment
- identity
- sequence
- hilo
- native
- assigned
具体的主键生成器策略有何作用这里就不多说了,如果要看请移步 starskyhu
途中遇到的问题和犯得错误:
- 数据表没有序列化导致异常
UserTest.hbm.xml
中id主键生成策略用了native报异常:序列不存在,网上查找了一下,说是oracle 数据库插入数据不能自增,可以创建sequence生成自增序列(还是一脸慒逼)- 用Hibernate自动生成的
hibernate.cfg.xml
配置文件中<session-factory name="">
需要把name=""
去掉 Disabling contextual LOB creation as createClob() method threw error:java.lang.reflect.InvocationTargetException
,项目运行正常,又去网上百度了一波,
有两种说法:- 一种是说Oracle数据库驱动版本的原因(过老?)
- 还有一种说法是(搞得我还是一头雾水):
It happens during the boot, when Hibernate tries to retrieve some meta information from the database
我英语不太好,但大概的意思就是当Hibernate试图从数据库检索一些元数据信息的时候发生了此异常。他们给出了解决方法: 在hibernate.cfg.xml
文件中添加以下属性<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
Hibernate的github地址:Hibernate
总结
通过对本次的项目配置,对Hibernate框架有了更清晰的了解,但还有许多知识等待扩充,但从各种异常当中也收获许多。不要怕异常,只有在失败中才能加深自己对这框架的理解和使用。接下来的一段时间里 让我们一起努力吧!