Hibernate:核心开发接口介绍

1.Configuration
    Configuration对象是进行配置信息的管理,用来产生SessionFactory,可以在configure方法中指定hibernate配置文件,默认配置文件名为hibernate.cfg.xml。

package com.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
    //SessionFactory中维护的最重要的东西就是数据库连接池
    private static final SessionFactory sessionFactory;

    static{
        try{
            sessionFactory =new AnnotationConfiguration().configure().buildSessionFactory();
        }catch(Throwable ex){
            System.err.println("初始化SessionFactory创建失败"+ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }
}
package com.hibernate.id;

import javax.persistence.Embeddable;

/*  实现Serializable接口的原因之一是:使用get或load方法时,需构建TeacherPK对象的实体,并作为第二个参数传进去
 *      load(Object object, Serializable id);
 *      get(Class clazz, Serializable id);
 */
public class TeacherPK implements java.io.Serializable{
    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;
    }

    //重载hashcode和equals方法来实现主键相等的判断
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof TeacherPK ){
            TeacherPK pk=(TeacherPK)obj;
            if(pk.getId()==this.id && pk.getName()==this.name)
                return true;
        }
        return false;
    }

    //比较,先比较hashcode,hashcode相同再用equals比较
    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}
package com.hibernate.id;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

/**
 * @author zj
 * 
 * Annotation配置联合主键的三种方式:
 * 1.TeacherPK上加@Embeddable,Teacher中的TeacherPK属性上加@Id;
 * 2.TeacherPK上无需加注解,Teacher中的TeacherPK属性上加@@EmbeddedId;
 * 3.TeacherPK上无需加注解,Teacher中无需定义TeacherPK属性,可以直接定义联合主键中的属性,并在各个属性上都加@Id,
 *   在Teacher上加@IdClass(value=TeacherPK.class)。
 *   其中:第2、3中比较常用。
 */
@Entity
@IdClass(value=TeacherPK.class)
public class Teacher {
    //private TeacherPK pk;
    private int id;
    private String name;
    private Date birthday;
    private int age;
    private String position;

    /*@EmbeddedId
    public TeacherPK getPk() {
        return pk;
    }
    public void setPk(TeacherPK pk) {
        this.pk = pk;
    }*/
    @Id
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Id
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Column(nullable=true)
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    //不允许字段参加hibernate SQL语句的更新
    @Column(updatable=false)
    public String getPosition() {
        return position;
    }
    public void setPosition(String position) {
        this.position = position;
    }
}

2.SessionFactory
    org.hibernate.SessionFactory是一个线程安全的Session工厂类,能为不同线程生成不同的Session。SessionFactory维护者Session相关的资源,包括数据库连接池、缓存数据等。
    注意openSession()和getCurrentSession()方法的区别:
     1)openSession()永远打开新的session;需要手动close。
    2)getCurrentSession()在session提交前(commit),如果原来有session,则直接拿已经存在的session,若没有则打开新的session;在session提交后session就消失了;事务提交时自动close。getCurrentSession的用处:同一个事务内的数据操作(如添加用户和记录添加用户日志,要么都完成,要么都失败),用于界定事务边界。
    上述两种方式不能混用,两种方式拿到的Session具体实现不同。

3.Session
1)可持久化对象的三种状态
    可持久化对象(Persistent Object)就是可以保存进数据库的对象,根据它在程序中的位置不同,可持久化对象可以有一下三种状态:

  • Transient(临时状态):对象在保存至数据库之前为临时状态,这时候数据库中没有该对象的信息,该对象的Id属性也为空。如果没有被持久化,程序退出时Transient状态的对象信息将会丢失。
  • Persistent(持久化状态):对象在保存进数据库后或者从数据库中加载后、并且没有脱离Session时为持久化状态。这时候数据库中有该对象的信息,该对象的Id为数据库中对应记录的主键值。由于还在Session中,持久化状态的对象可以执行任何有关数据库的操作,例如获取集合属性的值等。
  • Detached(分离状态):分离状态是对象曾经处于持久化状态、但是现在已经离开Session了。虽然分离状态的对象有Id值,有对应的数据库记录,但是已经无法执行有关数据库的操作。例如,读取延迟加载的集合属性,可能会抛出LazyInitializeException。

2)load方法和get方法的区别
    见下述代码中的注释。
3)update方法
    见下述代码中的注释。

package com.hibernate.test;

import java.util.Date;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.hibernate.id.Student;
import com.hibernate.id.StudentPK;
import com.hibernate.id.Teacher;
import com.hibernate.id.TeacherPK;
import com.hibernate.id.Title;
import com.hibernate.util.HibernateUtil;

/*
 * 1.Configuration对象的方法buildSessionFactory()
 *   SessionFactory
 *   Session:openSession,getCurrentSession
 * 2.Session
 *     对象的三种状态:Transisent、Persistent、Detached
 *   load与get的区别;
 *   update
 *   saveOrUpdate
 *   clear
 *   flush
 *   SchemaExport
 */
public class HibernateIdTest {
    private static SessionFactory sessionFactory;

    @BeforeClass
    public static void beforeClass(){
        sessionFactory=HibernateUtil.getSessionFactory();
    }

    @Test
    public void testTeacherSave(){
        /*TeacherPK pk=new TeacherPK();
        pk.setId(28);
        pk.setName("zhoumingming");*/
        Teacher s=new Teacher();
        s.setId(1);
        s.setName("baihe");
        //s.setPk(pk);
        s.setBirthday(new Date());

        Session session=sessionFactory.openSession();

        //Session session2=sessionFactory.getCurrentSession();

        session.beginTransaction();
        session.save(s);
        session.getTransaction().commit();
        session.close();
    }

    /*
     * 测试可持久化对象(Persistent Object)的三种状态:
     * 1.Transient(临时状态):内存中有一个对象,没有id,缓存中也没有
     * 2.Persistent(持久化状态):内存中有,内存和数据库中都有id
     * 3.Detached(分离状态):内存中无id,数据库中有id
     */
    public void testTeacher3State(){
        /**************Transient****************/
        Teacher s=new Teacher();
        s.setId(2);
        s.setName("mingming");
        s.setBirthday(new Date());
        s.setAge(25);
        s.setPosition("professor");

        Session session=sessionFactory.openSession();
        session.beginTransaction();
        session.save(s);
        /**************Persistent****************/
        session.getTransaction().commit();
        session.close();
        /**************Detached****************/

        s.setId(3);
        s.setName("jingjing");
        s.setBirthday(new Date());
        s.setAge(23);
        s.setPosition("adjunct professor");

        Session session2=sessionFactory.openSession();
        session2.beginTransaction();
        session2.save(s);
        /**************Persistent****************/
        session2.getTransaction().commit();
        session2.close();
        /**************Detached****************/

    }

    public void testTeacherDelete(){
        Teacher s=new Teacher();
        s.setId(3);
        s.setName("jingjing");

        Session session=sessionFactory.openSession();
        session.beginTransaction();
        session.delete(s);
        session.getTransaction().commit();
        session.close();
    }

    public void testTeacherLoad(){
        TeacherPK pk=new TeacherPK();
        pk.setId(2);
        pk.setName("mingming");
        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        //使用load获得是对象的代理,并没有真正的发出SQL语句,SQL语句是在访问对象属性的时候才发出(延迟到访问对象属性时才加载)
        //所要获取的对象不存在时,不报错,因为它根本就不发SQL语句
        Teacher t=(Teacher)session.load(Teacher.class, pk);
        System.out.println(t.getClass());//输出结果为:class com.hibernate.id.Teacher_$$_javassist_0,为Teacher的一个子类

        //此时获取对象的属性不存在时,报org.hibernate.ObjectNotFoundException
        System.out.println("load一个Teacher对象:"+t.getId()+" "+t.getName()+" "+t.getBirthday());

        session.getTransaction().commit();
        /* 在commit之后即session关闭之后访问t会报错:org.hibernate.LazyInitializationException
         * System.out.println("load一个Teacher对象:"+t.getId()+" "+t.getName()+" "+t.getBirthday());
         */
    }

    public void testTeacherGet(){
        TeacherPK pk=new TeacherPK();
        pk.setId(3);
        pk.setName("jingjing");
        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        //使用get获取对象是直接发出SQL语句,然后从数据库中拿到数据,装入对象(直接从数据库加载,不会延迟)
        //所要获取的对象不存在时,报java.lang.NullPointerException错
        Teacher t=(Teacher)session.get(Teacher.class, pk);
        System.out.println(t.getClass());//输出结果为:class com.hibernate.id.Teacher

        session.getTransaction().commit();
        System.out.println("get一个Teacher对象:"+t.getId()+" "+t.getName()+" "+t.getBirthday());
    }

    public void testTeacherUpdate1(){
        //更新transient状态的对象,需要事先设定好transient对象的id,否则会报错
        TeacherPK pk=new TeacherPK();
        pk.setId(3);
        pk.setName("jingjing");

        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        Teacher t=(Teacher)session.get(Teacher.class, pk);
        session.getTransaction().commit();

        //detached状态的对象,变persistent状态,同时数据库做更新

        t.setBirthday(new Date());
        t.setAge(25);
        t.setPosition("lecturer");
        Session session2=sessionFactory.getCurrentSession();
        session2.beginTransaction();
        session2.update(t);
        session2.getTransaction().commit();
    }

    public void testTeacherUpdate2(){
        //更新transient状态的对象,需要事先设定好transient对象的id,否则会报错
        TeacherPK pk=new TeacherPK();
        pk.setId(3);
        pk.setName("jingjing");

        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        Teacher t=(Teacher)session.get(Teacher.class, pk);
        //persistent状态的对象只要设定不同的字段就会发生更新,都不用写update就会更新,但若字段内容没变则不会更新
        t.setAge(42);
        session.getTransaction().commit();

    }

    @Test
    public void testTeacherClear(){
        TeacherPK pk=new TeacherPK();
        pk.setId(2);
        pk.setName("mingming");

        //缓存中有对象时,则直接从缓存中获取对象,不再从数据库中拿数据
        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        Teacher t=(Teacher)session.load(Teacher.class, pk);
        System.out.println(t.getClass()+t.getName());

        //作用:强制清除Session缓存。无这条代码时,仅发一次SQL语句;有这条代码时,则发两次SQL语句
        session.clear();

        Teacher t2=(Teacher)session.load(Teacher.class, pk);
        System.out.println(t2.getClass()+t2.getName());
        session.getTransaction().commit();

    }

    public void testTeacherFlush(){
        TeacherPK pk=new TeacherPK();
        pk.setId(2);
        pk.setName("mingming");

        Session session=sessionFactory.getCurrentSession();
        session.beginTransaction();
        Teacher t=(Teacher)session.load(Teacher.class, pk);
        t.setAge(22);
        //作用:强制将缓存内容和数据库内容做同步
        session.flush();
        t.setAge(23);
        //默认在commit时才将缓存内容和数据库内容同步
        session.getTransaction().commit();  
    }

    @Test
    public void testSchemaExport(){
        //在程序中生成建表语句,而不是xml文件中
        (new SchemaExport(new AnnotationConfiguration().configure())).create(true, true);
    }

    @AfterClass
    public static void afterClass(){
        sessionFactory.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值