首页 > 代码库 > Hibernate学习笔记
Hibernate学习笔记
[1]创建数据库
运行-->cmd
c:> mysql -uroot -p123456 //登陆到mysql
mysql> create datavase soldier default charater set utf8
mysql> create table s_user (id int ptimary key auto_increment , name varchar(20))
mysql> insert int s_user (name) values(‘京溪‘)
mysql> show create table s_user //查看方言
[3].添加jar包
新建Java工程,并添加如下jar包:
1.{hibernate_home}/ hibernate3.jar
2.{hibernate_home}/lib/required/*.jar
3.{hibernate_home}/lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar
4.数据库对应的JDBC驱动(例如mysql-connector-java-5.1.5-bin.jar)
[4].配置 hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="foo">
<!-- 配置数据库信息 -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="connection.url">
<![CDATA[jdbc:mysql://localhost:3306/soldier?useUnicode=true&characterEncoding=utf8]]>
</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!--显示执行的SQL语句 -->
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- 导入映射文件 -->
<mapping resource="cn/soldoer/domain/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
[5].配置 User.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">
<hibernate-mapping package="cn.soldoer.domain">
<class name="User" table="s_user">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="string" column="name" />
</class>
</hibernate-mapping>
[6].User.java
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString(){
return "[User : id="+id +", name="+name+"]";
}
}
[7].UserDao.java
package cn.soldoer.domain;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class UserDao {
public void add(User user) {
//添加事务
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();//开始事务
session.save(user);
tx.commit();//提交事务
} catch (Exception e) {
tx.rollback();//回滚事务
throw e;
} finally {
session.close();//关闭session
}
}
public void update(User user) {
Session session = HibernateUtils.openSession();
try {
session.beginTransaction();
session.update(user);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
throw e;
} finally {
session.close();
}
}
public void delete(int id) {
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
session.delete(getById(id));
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
public User getById(int id) {
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
User user = (User) session.get(User.class, id);
tx.commit();
return user;
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
@SuppressWarnings("unchecked")
public List<User> findAll() {
List<User> list = null;
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
list = session.createQuery(//
"FROM User")//
.list();
tx.commit();
return list;
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
@SuppressWarnings("unchecked")
public List<User> findAll(int firstResult, int maxResult) {
List<User> list = null;
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
list = session.createQuery(//
"FROM User")//
.setFirstResult(firstResult)//
.setMaxResults(maxResult)//
.list();
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
return list; }
}
[8].HibernateUtils.java
package cn.soldoer.domain;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
// SessionFactory 全局只有一个就可以了
private static SessionFactory sessionFactory;
static {
sessionFactory = new Configuration()//
.configure()//
.buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session openSession() {
return sessionFactory.openSession();
}
}
[9] ---API
Configuration 配置
configure()
configure(String resourse)
addClass(Class clazz)
addResource(String resourse)
buliSessionFactory()
SessionFactory Session工厂
openSession()
getCurrentSession()
colse()
Session
操作对象的方法
save(Object)
update(Object)
delete(Object)
查询的方法
createQuery(String)
createCriteria(class)
管理事务的方法
beginTransaction()
getTransaction()
其他的方法
...
工具类
Configuration cfg = new Configuration().configure();
SchemaExprot se = new SchemaExprot(cfg);
se.create(true,true)
Transaction 事务
commit()
rollback()
Query 查询
list()
uniqueResult()
Criteriar 查询
-----------------------------------
[10].Hibernate主配置文件
1.配置的key前面hibernate.前缀可以有也可以没有。
如:hibernate.dialect和dialect是一样的
2.按作用可分三类:
a.配置数据库信息:
<property ...>
方言 Jdbcurl 驱动类 用户名 密码
b.导入映射文件
<mapping ...>
c.其他配置
<property ...>
show_sql true false 显示生成的SQL语句
format_sql true false 格式化生成的SQL语句
hbm2dll.auto
|--create //先删除再创建
|--create-drop//启动时创建,关闭时删除
|--update//表不存在创建,表不一样就更新,一样什么也不做
|--validate//验证表结构是否一致,如果不一致抛异常
...
[11]xxx.hbm.xml映射文件配置
对持久化对象的要求:
a.提供一个无参构造器
b.提供一个标识属性
c.提供持久化对象字段属性
d.使用非final //懒加载支持
e.重写eqauls()和hashCode() //Set支持
OID - 对象唯一标识符
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--package 包名-->
<hibernate-mapping package="cn.soldoer.domain">
<!-- name:哪个类
table:哪个表
-->
<class name="User" table="s_user">
<!--主键:推荐实体使用Integer类型
子元素:generator是用于指定主键生成策略的
identity:使用数据库自己的主键生成策略,oracle不支持
sequence:使用序列作为主键生成策略的,Oracle数据库
hiol:使用高低位算法生成主键
<genrator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</genrator>
native:根据底层数据库的能力选择使用 idemtity、sequence、hiol中的一个。
uuid:由Hibernate自动生成uuid并指定为主键值。
increment:不推荐使用,会出现线程安全问题,因为是由Hibermate维护的自动增长。
-->
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<!--property普通 的属性(数据库中的值类型,字符串,日期,数字等)
name:实体名,必须
type:类型,可以写实体类型,也可以写在数据库中的类型 data time timestamp binary text
column:数据库中的字段名
length:长度
not-null:非空约束,默认为false
-->
<property name="name" type="string" column="name" / >
</class>
</hibernate-mapping>
[12] 获取Set
user.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">
<hibernate-mapping package="cn.soldier.set">
<class name="User" table="s_user">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="string" column="name" />
<!-- <set name="使用字段" table="集合表名"><key column="集合外键"></key> <element type="集合元素类型"
column="集合元素列名"></element> </set> -->
<!-- addressSet属性,Set集合 -->
<set name="addressSet" table="user_addressSet">
<key column="userId"></key>
<element type="string" column="address"></element>
</set>
<!-- addressList属性,list集合 table:集合表的名称 key: 集合外键的列名 list-index:存放集合索引列
element:存放集合元素的列的信息 -->
<list name="addressList" table="user_addressList">
<key column="userid"></key>
<list-index column="idx"></list-index>
<element type="string" column="address"></element>
</list>
<!-- addressArray属性,数组 table:集合表的名称 key: 集合外键的列名 list-index:存放集合索引列 element:存放集合元素的列的信息 -->
<array name="addressArray" table="user_addressArray">
<key column="userid"></key>
<list-index column="idx"></list-index>
<element type="string" column="address"></element>
</array>
<map name="addressMap" table="user_addressMap">
<key column="userid"></key>
<map-key type="string" column="key_"></map-key>
<element type="string" column="address"></element>
</map>
<!-- addressBag属性,Bag结合:无序可重复 与set集合基本一致 -->
<bag name="addressBag" table="user_addressBag">
<key column="userid"></key>
<element type="string" column="address"></element>
</bag>
</class>
</hibernate-mapping>
user.java
package cn.soldier.set;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class User {
private Integer id;
private String name;
private Set<String> addressSet = new HashSet<String>();// set集合
private List<String> addressList = new ArrayList<String>();// list集合
private String[] addressArray;// 数组
private Map<String, String> addressMap = new HashMap<String, String>();// map
private List<String> addressBag = new ArrayList<String>();
/*
* 使用集合属性是,一定要使用接口,而不能声明为具体的实现类, 因为经过Session操作后,集合就变成了Hibernate自己的集合实现类
*/
省略getter,setter
}
app.java
package cn.soldier.set;
import java.util.Arrays;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactroy = null;
static {
sessionFactroy = new Configuration().configure().addClass(User.class)
.buildSessionFactory();
}
@Test
public void testSave() {
Session session = sessionFactroy.openSession();
session.beginTransaction();
//
User user = new User();
user.setName("京溪");
user.getAddressSet().add("天河区");
user.getAddressSet().add("白云区");
//
user.getAddressList().add("你妹");
user.getAddressList().add("你妹妹");
user.getAddressList().add("你妹");
//
user.setAddressArray(new String[]{"呵呵","呵呵"});
//
user.getAddressMap().put("1","你妹");
user.getAddressMap().put("2","你妹妹");
//
user.getAddressBag().add("你妹");
user.getAddressBag().add("你妹");
user.getAddressBag().add("你妹111");
//
session.save(user);
//
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactroy.openSession();
session.beginTransaction();
//
User user = (User) session.get(User.class,5);
System.out.println("App.testGet():set"+user.getAddressSet() );
//
System.out.println("App.testGet():list"+user.getAddressList());
//
System.out.println("App.testGet():string[]"+Arrays.toString(user.getAddressArray()));
//
System.out.println("App.testGet():map"+user.getAddressMap());
//
System.out.println("App.testGet():bag"+user.getAddressBag());
session.getTransaction().commit();
session.close();
}
}
<!-- addressSet属性,Set集合 sort="unsorted|natural|comparatorClass" 由Hibernate在内存当中排序,一般不使用 -->
<set name="addressSet" table="user_addressSet" sort="natural">
<key column="userId"></key>
<element type="string" column="address"></element>
</set>
[13] 维护关联关系
对于一对多关系,就是设置外键列的值。
对于多对多关系,就是插入或删除中间表中的记录
cascade 级联
单向关联
单向多对一
单向一对多
单向多对多
单向一对一(只能做从有外键方到无外键方的单向关联)
双向关联
[14] 操纵持久化对象的状态
1.临时状态
与数据库没有对应,跟session没有关联
一般是新new出的对象,
2.持久化状态
对象在session的管理之中,最终会有对应的数据库记录
特点:
1.有OID
2.对对象的修改会同步到数据库中。
3.游离状态
数据库中有对应记录,但对象不再session管理之中是。
修改次状态对象是,数据库不会有变化。
4.删除状态
执行了session.delete()后的对
[15]session中的方法
一、操作实体对象的
sava()
update()
savaOrUpdae()
二、操作缓存的
clear()
evict()
flush()//默认(如:update delete)是在事务提交时执行 save是立刻执行
三、查询实体对象的
get()
load()
createQuery()
createCriteria()
加载方式 返回值 如果数据不存在
----------------------------------------------------------
get() 立即加载 返回真实对象或null 返回null
load() 延迟加载 返回代理对象 抛异常
[16] 操作大批量,要防止session中对象过多而内存溢出
java.lang.OutOfMemoryError: Java heap space
[17] Hibernate检索方式说明
1.导航对象图检索方式:根据已加载的对象导航到其他对象//eg.employee.getdepartment().getName();
2.OID检索方式:按照对象的OID来检索对象 //eg. session.get(clzz,id) session.load()
3.HQL检索方式:使用面向对象的HQL查询语言 //eg. session.createQuery();
4.QBC检索方式:使用QBC(Query By Criterie) API 来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口
5.本地sQL检索方式:使用本地数据库的SQL查询语句
[17]懒加载
也叫延迟加载,不是在执行获取操作是拿上生成sql。而是在第一次使用时生成sQL。
分成两种:
类级别的:
<class ... lazy="true/false">
属性级别的:
<set/list/map/bag ... lazy=""...>
<many-to-one ...>
<one-to-one> ... lazy="..."
使用懒加载特性时,可能会有LazyInitizlizationException异常:
原因:
真正的获取数据时,Session已经没有了。
解决办法:
方式一:让session在真正加载后再关闭,
方式二:让Session关闭前执行(Hibernate.initialize()) eg.Hibernate.initialize(department.getEmployees());
[18].使用c3p0数据库连接池
hibernate.connection.provider_class: 该类用来向 Hibernate 提供JDBC连接
hibernate.c3p0.max_size: 数据库连接池的最大连接数
hibernate.c3p0.min_size: 数据库连接池的最小连接数
hibernate.c3p0.timeout: 数据库连接池中连接对象在多长时间没有使用过后,就应该被销毁
hibernate.c3p0.max_statements: 缓存 Statement 对象的数量
hibernate.c3p0.idle_test_period: 表示连接池检测线程多长时间检测一次池内的所有链接对象是否超时. 连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次被使用时间和当前时间的时间差来和 timeout 做对比,进而决定是否销毁这个连接对象。
hibernate.c3p0.acquire_increment: 当数据库连接池中的连接耗尽时, 同一时刻获取多少个数据库连接
hibernate.c3p0.validate: 是否每次连接都验证连接是否可用
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
[19]. 二级缓存
Hibernate中提供了两个级别的缓存
第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存。
这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预
第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存
SessionFactory 的缓存可以分为两类:
内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段,
Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中,
映射元数据是映射文件中数据的复制, 而预定义 SQL 语句时 Hibernate 根据映射元数据推到出来的. 该内置缓存是只读的.
外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件.
外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘
配置步骤
1拷贝ehcache-1.5.0.jar到当前工程的lib目录下
2开启二级缓存
<property name="hibernate.cache.use_second_level_cache">true</property>
3指定缓存的供应商
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
4指定使用二级缓存的类
方法一 在使用类的*.hbm.xml配置
<class>元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性,
但不会缓存集合属性, 若希望缓存集合属性中的元素,
必须在 <set> 元素中加入 <cache> 子元素
方法二 在hibernate.cfg.xml文件中配置(建议)
<!-- 指定使用二级缓存的类 放在maping下面 -->
<!-- 配置类级别的二级缓存 -->
<class-cache class="cn.itcast.c3p0.Customer" usage="read-write"/>
<class-cache class="cn.itcast.c3p0.Order" usage="read-write"/>
<!-- 配置集合级别的二级缓存 -->
<collection-cache collection="cn.itcast.c3p0.Customer.orders" usage="read-write"/>
不管是一级缓存,还是二级缓存,都是子啊使用OID的获取对象是才有效。
get(),load()
对于Query.list()默认不会使用缓存,哪怕写成where id-=1 也不会使用换缓存
使用查询缓存的步骤
配置二级缓存, 因为查询缓存依赖于二级缓存
在 hibernate 配置文件中启用查询缓存
<property name="cache.use_query_cache">true</property>
对于希望启用查询缓存的查询语句, 调用 Query 的 setCacheable(true) 方法
Update \_____不会通知session缓存
Delete / 会把对应的二级缓存移除
绑定参数的形式,按参数名称绑定
hql 查询:
Query query = session.createQuery("from Customer c where " +
" c.name=:custname and c.age=:custage");
//第一个参数代表名字,第二个参数代表值
query.setString("custname", "Tom");
query.setInteger("custage", 21);
List list = query.list();
绑定参数的形式,按参数位置绑定
Query query = session.createQuery("from Customer c where c.name=? and c.age=?");
query.setString(0,"Tom");
query.setInteger(1, 21);
query.list();
Hibernate学习笔记