Hibernate简介
:Hibernate的创始人Gavin King,EJB(企业 java bean) 3.0专家委员会成员,JBoss(一个服务器)核心成员之一
Hibernate中Java对象的三种状态
瞬时状态(Transient)
持久状态(Persistent)
游离状态(Detached)
new对象 -----==> 临时状态
临时状态 -----==> 持久状态 get、load
持久状态 -----==> 游离状态 close、clear、evict
游离状态 -----==> 持久状态 update
持久状态 -----==> 临时状态 delete
游离状态 -----==> 临时状态 delete
Hibernate优缺点
Hibernate优点:
1、简化了JDBC 繁琐的编码
Session session = HiberanteUtil.currentSession();
Query query = session.createQuery("from User");
List<User> users = (List<User>) query.list();
2、对面向对象特性支持良好
3、可移植性好
Hibernate的缺点
1、不适合需要使用数据库的特定优化机制的情况(各种数据库的共性)
2、不适合大规模的批量数据处理(大规模增删改略慢)
Hibernate的步骤
1、下载并部署jar文件
Hibernate官方网站:http://hibernate.org
Hibernate托管网站:https://sourceforge.net/projects/hibernate/files/
部署jar文件 | 文件内容 |
---|---|
hibernate3.jar | |
lib\required目录下的jar文件 | |
lib\jpa\hibernate-jpa-2.0-api-1.0.1.Final.jar | |
Oracle数据库驱动jar文件 | |
antlr-2.7.7.jar | 辅助jar包 |
dom4j-1.6.1.jar | 解析xml文件 |
hibernate-commons-annotations-4.0.1.Final.jar | 通用注解 |
hibernate-core-4.1.1.Final.jar | 核心包 |
hibernate-entitymanager-4.1.1.Final.jar | 管理 |
hibernate-jpa-2.0-api-1.0.1.Final.jar | 在jpa基础上 |
javassist-3.15.0-GA.jar | 字节码处理 |
jboss-logging-3.1.0.GA.jar | 日志 |
jboss-transaction-api_1.1_spec-1.0.0.Final.jar |
2、编写Hibernate配置文件
用于配置数据库连接,运行时所需的各种特性,一般命名为“hibernate.cfg.xml“保存在src目录下
<?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="connection.url">jdbc:mysql://localhost:3306/house</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 显示sql -->
<property name="show_sql">true</property>
<!-- 格式化sql -->
<property name="format_sql">true</property>
<property name="current_session_context_class">thread</property>
<!-- 当前数据库之间的方言 -->
<property name=“dialect”>org.hibernate.dialect.MySQLDialect</property>
<!-- 实体映射文件 -->
<mapping resource="com/cfn/bean/Users.hbm.xml" />
<mapping resource="com/cfn/bean/UserInfo.hbm.xml" />
</session-factory>
</hibernate-configuration>
关于 <property name="current_session_context_class">thread</property>
sessionFactory.getCurrentSession()可以完成一系列工作,当调用是hibernate将session绑定到当前线程,事务结束后hibernate将session从当前线程中释放并且关闭session。当再次调用getCurrentSession()时将得到一个新的session,并重新开始这一系列工作。
调用方法如下:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
session.getTransaction().commit(); //不需要close session了。 前提是改值设置为了thread.
Hibernate 不同数据库的连接及SQL方言:http://www.cnblogs.com/gxbk629/p/4508995.html
易错点: mapping写到proprety之后
3、创建持久化类和映射文件
A、定义持久化类(也称实体类),实现java.io.Serializable 接口,添加默认构造方法,配置文件中最好用包装类
public class Users implements java.io.Serializable{
private Integer id;
private String name;
private String password;
private String telephone;
private String username;
private String idadmin;
//省略getter&setter方法、以及构造方法
}
B、配置映射文件(*.hbm.xml),位置在实体类同包下,相当于把对应数据库bean类存进去
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "com.cfn.bean.Users" table = "users">
<id name="id" column="ID" type="java.lang.Integer">
<!--
native由hibernate根据使用的数据库自行判断
采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。
如果能支持identity则使用identity,如果支持sequence则使用sequence。
-->
<generator class="native"></generator>
</id>
<property name="name" column="NAME" type="java.lang.String"></property>
<property name="password" column="PASSWORD" type="java.lang.String"></property>
<property name="telephone" column="TELEPHONE" type="java.lang.String"></property>
<property name="username" column="USERNAME" type="java.lang.String"></property>
<property name="isadmin" column="ISADMIN" type="java.lang.String"></property>
</class>
</hibernate-mapping>
Hibernate各种主键生成策略与配置详:http://www.cnblogs.com/hoobey/p/5508992.html
C、别忘了,还有最后一步:向hibernate.cfg.xml文件中配置映射文件
<session-factory>
<!-- 省略其他配置 -->
<mapping resource="cn/hibernatedemo/entity/Dept.hbm.xml" />
</session-factory>
4、使用Hibernate API
public static void main(String[] args) {
Configuration cf = null;
SessionFactory sf = null;
Session session = null; //不是会话session
Transaction tx = null;
//1:读取配置文件
cf = new Configuration().configure();
//2:创建sessionfactory
sf = cf.buildSessionFactory();
//3:创建session
session = sf.getCurrentSession();
//4:开启事务
tx = session.beginTransaction();
//根据userid = 60去查询用户信息
Users u = (Users) session.get(Users.class, new Integer(60));
System.out.println(u.getId() + "\t" + u.getName() + "\t" + u.getTelephone());
}
A、通过主键值加载指定类型的实例
方 法 | 区 别 |
---|---|
Object get(Class clazz, Serializable id) | 若数据不存在,返回null |
Object load(Class clazz, Serializable id) | 若数据不存在,使用时抛ObjectNotFoundException |
主键生成器不要使用assigned,用navicat
B、更新数据的方法
方 法 | 区 别 |
---|---|
update() | |
saveOrUpdate() | 返回void |
merge() | 返回Object对象 |
C、使用HibernateUtil,封装事务,创建会话时,只需要调用Util即可
public class HibernateUtil {
static Configuration cf = null;
static SessionFactory sf = null;
//若使用openSession()开启会话,则需关闭
static Session session = null; //不是会话session
public static Transaction tx = null;
static{
cf = new Configuration().configure();
sf = cf.buildSessionFactory();
}
public static Session getCurrentSession(){
session = sf.getCurrentSession();
tx = session.beginTransaction();
return session;
}
}
/**
* 测试用例
* 查询单个用户信息
*/
@Test
public void queryOne(){
Session session = HibernateUtil.getCurrentSession();
Users user = (Users) session.get(Users.class, 60);
// get方法查不到时返回null,所以此处判断空
if(user != null){
System.out.println(user.getId());
}
}
/**
* 增加用户信息
*/
@Test
public void addUser(){
Users user = new Users();
user.setName("hibernate");
user.setPassword("123456");
Session session = HibernateUtil.getCurrentSession();
session.save(user);
//提交事务 适用于增加 删除 修改 否则数据库没有变化
HibernateUtil.tx.commit();
}
/**
* 修改用户信息
*/
@Test
public void updateUser(){
Session session = HibernateUtil.getCurrentSession();
// 获取要修改的对象
Users user = (Users) session.load(Users.class, 60);
//修改名字
user.setName("小明"); //此时与数据库中的数据不一致,该对象为脏对象
HibernateUtil.tx.commit(); // commit 方法会首先刷新缓存
//刷缓存时,Hiberante会对Session中持久状态的对象进行检测,判断对象的数据是否发生了改变
//刷新缓存就是将数据库同步为与Session缓存一致
//刷新缓存时会执行脏检查
//Session会在以下时间点刷新缓存
//调用Session的flush()方法
//调用Transaction的commit()方法
}
/**
* 删除
*/
@Test
public void deleteUser(){
Session session = HibernateUtil.getCurrentSession();
//找到删除对象
Users user = (Users) session.get(Users.class, 60);
if(user != null){
session.delete(user);
HibernateUtil.tx.commit();
}
}
@Test
public void saveOrUpdate(){
Session session = HibernateUtil.getCurrentSession();
Users u = (Users) session.load(Users.class, 77);
//当状态为临时状态,这个执行save
//当对象是持久状态,再set值的时候,执行update
// insert
u.setName("赵子龙");
u.setPassword("123456");
session.saveOrUpdate(u);
// update
Users user = (Users) session.load(Users.class, 77);
user.setName("赵云");
user.setPassword("33333");
session.saveOrUpdate(user);
HibernateUtil.tx.commit();
}
@Test
public void meger(){
Session session = HibernateUtil.getCurrentSession();
Users user = new Users();
user.setName("赵云");
user.setPassword("33333");
Users u = (Users) session.merge(user);
System.out.println("获取增加后的对象名称:" + u.getName());
HibernateUtil.tx.commit();
}
@Test
public void megerSave(){
Session session = HibernateUtil.getCurrentSession();
Users user = (Users) session.load(Users.class, 1010);
user.setName("赵云1");
user.setPassword("33333");
Users u = (Users) session.merge(user);
System.out.println("获取修改后的对象名称:" + u.getName());
HibernateUtil.tx.commit();
}