*瞬时对象(Transient Objects):使用new 操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。
*持久化对象(Persist Objects):持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。
*离线对象(Detached Objects):Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。
*transient状态的特征?没在缓存中,没任何对象引用
在数据库中没有与之匹配的数据
没有纳入session的管理
*persistent状态的特征?在缓存中,有对象引用
persistent状态的对象在数据库中有与之匹配的数据(uuid是没有的)
纳入了session的管理(save的时候放到缓存一份,放到了session的mapping中)
在清理缓存(脏数据检查)的时候,会和数据库同步
*detached状态的特征?从缓存中清了,没有任何对象引用
在数据库中有与之匹配的数据
没有纳入session的管理
Hibernate_session:
工具类:HibernateUtils
/**
*使SessionFactory只初始一次
*/
public class HibernateUtils {
private static SessionFactory factory;
//调用类的static只初始化一次,因此factory只有一个
static {
try{
Configuration cfg = new Configuration().configure();
factory = cfg.buildSessionFactory();
}catch(Exception e){
e.printStackTrace();
}
}
public static SessionFactory getSessionFactory(){
return factory;
}
public static Session getSession(){
return factory.openSession();
}
public static void closeSession(Session session){
if(session != null){
if(session.isOpen()){
session.close();
}
}
}
}
* junit简介:(建源代码目录,放测试类***Test)
编写测试类xxxTest,需要继承TestCase
编写单元测试方法,测试方法必须以test开头,测试方法不能含有参数和返回值,如:
public void testHello1() {}
最好单元测试的代码单独建立一个目录(建立一个源代码文件),但运行的时候class还是放在一起的。
setUp():公用的东西可以放在这个方法里,相当于Servlet中的init();
* SessionFactory:一个重量级对象,和二级缓存绑定.通常只创建一次。
*session:不要声明成成员变量,不是线程安全的,不要多线程来用,通常一个业务对以一个session,一个方法对应一个session,请求完毕,session关闭,事务关闭。
*三个状态:
public void testSave1(){
Session session = null;
User user = null;
Transaction tx = null;
try{
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//Transient 瞬时状态,不会序列化
user = new User();
user.setName("李四");
user.setPassword("123456");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//persistent 状态:当属性发生改变,commit的时候Hibernate会自动和数据库同步,自动同步:不用显示写update
//所以数据库中存放的是:王五
session.save(user);//save之后必须要有id,此时是hibernate提供的,没去数据库取
user.setName("王五");
//uuid状态:commit之前数据库没有数据,commit之后清理缓存,发sql到数据库. Commit后会脏数据检查,所以会发insert和update两条语句
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeSession(session);
}
//detached状态
user.setName(“张三”); 要把user变成这个函数的成员变量
/**
*存user:update
*/
//此时数据库变化:王五变为张三
}
/**
* get方法,查不到会返回null
*/
public void testReadByGetMethod(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//马上发查询sql,加载User对象;根据id查user,id要实现序列化的
User user = (User)session.get(User.class,"402881e42302c687012302c689720001");
System.out.println("User.Name:"+user.getName());
//persistent状态,属性改变时,Hibernate自动和数据库同步,不用显示update
user.setName("郭杰"); //查出来的name改为郭杰,数据库里也为郭杰,其他字段保持不变
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
/**
* get方法2
*/
public void testReadByGetMethod2(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//马上发出sql,加载User对象;查不到会返回null
User user = (User)session.get(User.class,"0001");
System.out.println(user);//null
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
/**
* Load方法
*/
public void testReadByLoadMethod(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,load只有真正使用的时候才加载(lazy),下面要输出了才加载(发出sql) 和get的区别
//延迟加载实现原理:CGLIB动态代理方式
User user = (User)session.load(User.class,"402881e422e421500122e421528a0001");//此时user对象为代理对象,下面要用了才去真正查询
System.out.println("User.Name:"+user.getName());
//persistent状态,属性改变时,Hibernate自动和数据库同步
user.setName("郭杰");
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
/**
* Load:注意和get的两个区别:1、load延迟加载,2、无数据时load报错
*/
public void testReadByLoadMethod2(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
// load只有真正使用的时候才加载(lazy),下面要输入才发sql,和get的区别
//数据库中没有这个id的时候load会抛出异常 和get的第二个区别
User user = (User)session.load(User.class,"0001");
//下面注释掉不会抛出异常,因为没发sql,即没load
//没注释掉会报错,但是仍显示绿色条,因为没向上抛.见下面的catch语句
//System.out.println("User.Name:"+user.getName());
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
//下面那句注释掉就会显示绿色,只有往上抛了才显示红色
throw new java.lang.RuntimeException();
}finally{
HibernateUtils.closeSession(session);
}
}
/**
* update
*/
public void testUpdate1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//手动构造的detached状态的对象,因为new的时候id是数据库中已存在的,所以detached状态。New的时候如果数据库中没有为Transient瞬时状态
//结果没设置的属性都变成了null
//所以一般先加载(get load)上来,再修改,就像上面的例子
User user = new User();
user.setId("402881e422e421500122e421528a0001");//id必须要和数据库中已有的一样,这是hibernate生成的,不能更改
user.setName("德华");
session.update(user);//只有detached状态才可以update.
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
*get load 都是根据主键加载
/**
* 删除方法,只能删除persistent状态
*/
public void testDelete1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//先加载上来在删除
User user = (User)session.load(User.class, "402881e422e421500122e421528a0001");
session.delete(user);//此时user对象transient状态
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
*了解Hibernate中CRUD操作
*了解get和load的区别?
* get不支持lazy,load支持lazy
* 采用get加载数据,如果没有匹配的数据,返回null,而load则抛出异常
*transient状态的特征?瞬时的
* 在数据库中没有与之匹配的数据
* 没有纳入session的管理
*persistent状态的特征?持久的
* persistent状态的对象在数据库中有与之匹配的数据(uuid是没有的)
* 纳入了session的管理
* 在清理缓存(脏数据检查)的时候,会和数据库同步
*detached状态的特征?离线
* 在数据库中有与之匹配的数据
* 没有纳入session的管理
*uuid:save()之后:变成persistent状态,数据库中没数据 commit()之前数据库没有记录,commit()之后清理缓存,发sql,数据库中有记录
Query实例:
public class QueryTest extends TestCase {
public void testQuery(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//from 后面区分大小写 因为查的是实体类
String hql = "from User";
Query query = session.createQuery("from User");
//query的分页,setFirstResult:第几条开始,2:表示第三条 0:表示第一条。后面的表示查询几条
query.setFirstResult(2);
query.setMaxResults(2);
List<User> userList = query.list();
for(User ue: userList){
System.out.println(ue.getId());
System.out.println(ue.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
*一个OR框架包括:映射(ormapping)、Hql、缓存等等。
*OR框架:批量查询可以:Query; 有统计函数、批量修改、批量删除不适合!
*Query接口支持HQL 和SQL
*通过<property>标签将普通属性映射成表字段,所谓普通属性指不包括自定义类、集合和数组等.主键用<id>
*注意:如果实体类和实体类中的属性和sql中的关键字重复,必须采用table或column重新命名
*实体类的普通属性映射成表字段. 普通属性:输了list map set 数组等
*<class>标签映射成数据库的表,<property>标签普通属性映射成表字段.
*主键生成策略:
uuid、native和assigned
*hql查询的是实体类