Hibernate学习---第二节:hibernate 增、删、改、查

1、增,向数据库中写入数据,代码如下:

/**
 * 数据保存
 * 1、save()
 * 2、persist()
 */
@Test
private void testSave(){
    Configuration config = new Configuration().configure();
    /**
     * 获取连接工程场
     * 通常对应一个数据库,通常一个应用程序只有一个,再启动的时候创建
     * 线程安全
     */
    /**
     * buildSessionFactory() 属于 hibernate3 中的方法
     */
    SessionFactory factory = config.buildSessionFactory();
    
    /**
     * 获得 session ,session 是 Hibernate 的核心  API,增删改查都是通过 session 完成
     * session 相当于一次数据库表的操作
     * 飞线程安全
     */
    Session session = factory.openSession();
    
    /**
     * hibernate 对数据的 增、删、改 需要食物的支持
     */
    Transaction tx = session.beginTransaction();
    
    Person p = new Person("zxx",22,123456, new Date());
    /**
     * 将 person 对象持久化的数据库中
     * save() 会将数据立即写入到数据库表中
     */
    /*Integer id = (Integer)session.save(p);
    
    System.out.println("持久化标识符=="+id);*/
    
    /**
     * 在 hibernate4 中推荐使用
     * persist() 可能不会被立即写入数据库,延迟写入,性能略高
     */
    session.persist(p);
    
    /**
     * 提交事务
     */
    tx.commit();
    /**
     * 关闭 session
     */
    session.close();
}

注:save() 和 persist() 的比较(区别):

(1)、保存持久化对象时,该方法返回该持久化对象的标识属性值(即主键)。该方法会立即将持久化对象的对应数据插入数据库。

(2)、该方法没有返回任何值。保证当它在一个事务外部被调用时,并不立即转换为insert语句。适用于长会话流程。

hibernate 文档说明:

(1)、persist把一个瞬态的实例持久化,但是并"不保证"标识符被立刻填入到持久化实例中,标识符的填入可能被推迟
到flush的时间。

(2)、persist"保证",当它在一个transaction外部被调用的时候并不触发一个Sql Insert,这个功能是很有用的,当我们通过继承Session/persistence context来封装一个长会话流程的时候,一个persist这样的函数是需要的。

(3)、save"不保证"第2条,它要返回标识符,所以它会立即执行Sql insert,不管是不是在transaction内部还是外部

2、删除数据,代码如下:

/**
 * 创建临时对象,做删除
 */
@SuppressWarnings("deprecation")
@Test
private void TestRemove(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    Person p = new Person();
    p.setId(4);
    session.delete(p);
    
    tx.commit();
    session.close();
}

/**
 * 获取持久化对象,做删除
 */
@SuppressWarnings("deprecation")
@Test
private void TestDelete(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    Person p = (Person)session.load(Person.class, 3);
    session.delete(p);
    
    tx.commit();
    session.close();
}

3、修改数据库中的数据,代码如下:

/**
 * 更新
 */
@SuppressWarnings("deprecation")
@Test
private void testMerge(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    
    Transaction tx = session.beginTransaction();
    
    //Person p = (Person)session.get(Person.class, 5);
    
    Person p = new Person();
    p.setName("周大福8999ffff");
    
    // person 是持久化状态对象,当 session 关闭之后,数据库中的 name所对应的字段更改为 "NMNMN" 
    Person person = (Person)session.merge(p);
    person.setName("NMNMN");
    p.setName("ghjhjh");
    
    tx.commit();
    session.close();
}

/**
 * 更新
 */
@SuppressWarnings("deprecation")
@Test
private void testRevise(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    // person 对象是持久化状态,当 session 关闭的时候数据会被更新到数据库中
    // 如果要更新的数据与数据库中的数据是一样的,那么 session 关闭的时候不会往数据库中发更新操作
    Person p = (Person)session.get(Person.class, 5);
    p.setName("周大福8999");
    
    tx.commit();
    session.close();
}

/**
 * 更新
 * 瞬时状态:不曾进行持久化,未与任何 session 相关联
 * 持久化状态:当前仅与一个 session 有关联,session 关闭或 session 同步的时候会将数据更新到数据库中
 * 脱管状态:已经进行过持久化,但当前未与任何 session 相关联
 */
@SuppressWarnings("deprecation")
@Test
private void testModify(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    Person p = new Person();
    p.setId(5);
    p.setName("周大福22");
    session.update(p);
    
    tx.commit();
    session.close();
}

/**
 * 更新
 */
@SuppressWarnings("deprecation")
@Test
private void testUpdate(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    Person p = (Person)session.get(Person.class, 5);
    p.setName("周大福");
    session.update(p);
    
    tx.commit();
    session.close();
}

/**
 * 更新或保存
 */
@SuppressWarnings("deprecation")
@Test
private void testSaveorUpdate(){
    Configuration config = new Configuration().configure();
    
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    
    Person p = new Person();
    p.setId(3);
    p.setName("tom");
    p.setAge(22);
    p.setPasswork(123456);
    /**
     * 新增或更新,根据 id 是否存在,id 存在就更新,不存在就新增
     * 如果给定的 id 没有指定的记录,将报更新失败
     */
    session.saveOrUpdate(p);
    
    tx.commit();
    session.close();
}

4、查询数据库中的数据,代码如下:

/**
 * 数据库查询
 * 1、get()
 * 2、load()
 */
@SuppressWarnings("deprecation")
@Test
private void testSel(){
    Configuration config = new Configuration().configure();
    
    /**
     * hibernate4  使用如下的方法  实现服务注册方法获取 SessionFactory
     * 更加高效和安全
     */
    ServiceRegistry sr = new ServiceRegistryBuilder()
    .applySettings(config.getProperties()).buildServiceRegistry();
    
    SessionFactory factory = config.buildSessionFactory(sr);
    
    Session session = factory.openSession();
    
    /**
     * 立即查询,立即发送 sql 语句查询,并返回,不是代理对象
     * 如果给定的 id 没有对应的记录,则返回 null,不会报空指针异常;如果报空指针异常,则是对空指针进行了操作
     */
    Person p = (Person)session.get(Person.class, 3);
    System.out.println("--1--------------get---------------");
    System.out.println(p);
    System.out.println("--2--------------get---------------");
    
    /**
     * 延迟查询,返回的是一个代理对象,真正使用对象属性的是候才发起 sql 语句查询
     * 如果给定的 id 没有对应的记录,将报  ObjectNotFoundException 异常
     * 可以在持久化的配置文件中将延长查询改为立即查询
     */
    Person person = (Person)session.load(Person.class, 3);
    System.out.println("--1--------------load---------------");
    System.out.println(person);
    System.out.println("--2--------------load---------------");
    
    session.close();
}

注:get() 和 load() 的比较(区别):

(1)、从返回结果上对比:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null

(2)、从检索执行机制上对比:get方法和find方法都是直接从数据库中检索 而load方法的执行则比较复杂首先查找session的persistent Context中是否有缓存,如果有则直接返回 如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null 在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果找不到就抛出异常。

(3)、根本区别说明:
如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来 延迟加载该对象。在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常。所说的load方法抛异常是指在使用 该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时(注意:这就是由于“延迟加载”在作怪)。

由于session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。

对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。

对于load和get方法返回类型:虽然好多书中都这么说:“get()永远只返回实体类”,但实际上这是不正确的,get方法如果在 session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是 原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是 返回的还是代理对象,只不过已经加载了实体数据。

get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。

5、详细代码如下:

package learn.hibernate.test;

import java.util.Date;

import learn.hibernate.bean.Person;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;

public class HibernateTest {

    public static void main(String[] args){
        
        /**
         * Configuration 是 hibernate 的入口,负责管理 Hibernate 的配置信息,
         * 这些配置信息都是从配置文件 hibernate.cfg.xml 或者 Hibernate.properties
         */
        /**
         *  使用configure()方法加载默认的hibernate.cfg.xml配置文件,
         *  因为配置文件中已经含有数据库映射信息,因此就不需要使用addClass方法加载各个类文件的映射文件
         */
        Configuration config = new Configuration().configure();
        
        /**
         *  Configuration 的实例会根据当前的配置信息,构造SessionFactory实例。
         *  SessionFactory 是线程安全的,一般情况下一个应用中数据库共享一个 SessionFactory 实例。
         *  Hibernate 的 SessionFactory 接口提供 Session 类的实例,Session 类用于完成对数据库的操作。
         *  由于 SessionFactory 实例是线程安全的(而 Session 实例不是线程安全的),
         *  所以每个操作都可以共用同一个 SessionFactory 来获取 Session。
         */
        SessionFactory sessionFactory = config.buildSessionFactory();
        
        Session session = sessionFactory.openSession();
        
        Transaction tx = session.beginTransaction();
        Person person = new Person("hwl",19, 123456, new Date());
        session.save(person);
        tx.commit();
        session.close();
        // 通常不需要手动关闭
        sessionFactory.close();
    }
    
    /**
     * 数据保存
     * 1、save()
     * 2、persist()
     */
    @Test
    private void testSave(){
        Configuration config = new Configuration().configure();
        /**
         * 获取连接工程场
         * 通常对应一个数据库,通常一个应用程序只有一个,再启动的时候创建
         * 线程安全
         */
        /**
         * buildSessionFactory() 属于 hibernate3 中的方法
         */
        SessionFactory factory = config.buildSessionFactory();
        
        /**
         * 获得 session ,session 是 Hibernate 的核心  API,增删改查都是通过 session 完成
         * session 相当于一次数据库表的操作
         * 飞线程安全
         */
        Session session = factory.openSession();
        
        /**
         * hibernate 对数据的 增、删、改 需要食物的支持
         */
        Transaction tx = session.beginTransaction();
        
        Person p = new Person("zxx",22,123456, new Date());
        /**
         * 将 person 对象持久化的数据库中
         * save() 会将数据立即写入到数据库表中
         */
        /*Integer id = (Integer)session.save(p);
        
        System.out.println("持久化标识符=="+id);*/
        
        /**
         * 在 hibernate4 中推荐使用
         * persist() 可能不会被立即写入数据库,延迟写入,性能略高
         */
        session.persist(p);
        
        /**
         * 提交事务
         */
        tx.commit();
        /**
         * 关闭 session
         */
        session.close();
    }
    
    /**
     * 数据库查询
     * 1、get()
     * 2、load()
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testSel(){
        Configuration config = new Configuration().configure();
        
        /**
         * hibernate4  使用如下的方法  实现服务注册方法获取 SessionFactory
         * 更加高效和安全
         */
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        
        Session session = factory.openSession();
        
        /**
         * 立即查询,立即发送 sql 语句查询,并返回,不是代理对象
         * 如果给定的 id 没有对应的记录,则返回 null,不会报空指针异常;如果报空指针异常,则是对空指针进行了操作
         */
        Person p = (Person)session.get(Person.class, 3);
        System.out.println("--1--------------get---------------");
        System.out.println(p);
        System.out.println("--2--------------get---------------");
        
        /**
         * 延迟查询,返回的是一个代理对象,真正使用对象属性的是候才发起 sql 语句查询
         * 如果给定的 id 没有对应的记录,将报  ObjectNotFoundException 异常
         * 可以在持久化的配置文件中将延长查询改为立即查询
         */
        Person person = (Person)session.load(Person.class, 3);
        System.out.println("--1--------------load---------------");
        System.out.println(person);
        System.out.println("--2--------------load---------------");
        
        session.close();
    }
    
    /**
     * 更新
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testMerge(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        
        Transaction tx = session.beginTransaction();
        
        //Person p = (Person)session.get(Person.class, 5);
        
        Person p = new Person();
        p.setName("周大福8999ffff");
        
        // person 是持久化状态对象,当 session 关闭之后,数据库中的 name所对应的字段更改为 "NMNMN" 
        Person person = (Person)session.merge(p);
        person.setName("NMNMN");
        p.setName("ghjhjh");
        
        tx.commit();
        session.close();
    }
    
    /**
     * 更新
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testRevise(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        // person 对象是持久化状态,当 session 关闭的时候数据会被更新到数据库中
        // 如果要更新的数据与数据库中的数据是一样的,那么 session 关闭的时候不会往数据库中发更新操作
        Person p = (Person)session.get(Person.class, 5);
        p.setName("周大福8999");
        
        tx.commit();
        session.close();
    }
    
    /**
     * 更新
     * 瞬时状态:不曾进行持久化,未与任何 session 相关联
     * 持久化状态:当前仅与一个 session 有关联,session 关闭或 session 同步的时候会将数据更新到数据库中
     * 脱管状态:已经进行过持久化,但当前未与任何 session 相关联
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testModify(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        Person p = new Person();
        p.setId(5);
        p.setName("周大福22");
        session.update(p);
        
        tx.commit();
        session.close();
    }
    
    /**
     * 更新
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testUpdate(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        Person p = (Person)session.get(Person.class, 5);
        p.setName("周大福");
        session.update(p);
        
        tx.commit();
        session.close();
    }
    
    /**
     * 更新或保存
     */
    @SuppressWarnings("deprecation")
    @Test
    private void testSaveorUpdate(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        Person p = new Person();
        p.setId(3);
        p.setName("tom");
        p.setAge(22);
        p.setPasswork(123456);
        /**
         * 新增或更新,根据 id 是否存在,id 存在就更新,不存在就新增
         * 如果给定的 id 没有指定的记录,将报更新失败
         */
        session.saveOrUpdate(p);
        
        tx.commit();
        session.close();
    }
    
    /**
     * 创建临时对象,做删除
     */
    @SuppressWarnings("deprecation")
    @Test
    private void TestRemove(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        Person p = new Person();
        p.setId(4);
        session.delete(p);
        
        tx.commit();
        session.close();
    }
    
    /**
     * 获取持久化对象,做删除
     */
    @SuppressWarnings("deprecation")
    @Test
    private void TestDelete(){
        Configuration config = new Configuration().configure();
        
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        
        SessionFactory factory = config.buildSessionFactory(sr);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        
        Person p = (Person)session.load(Person.class, 3);
        session.delete(p);
        
        tx.commit();
        session.close();
    }
}

6、持久化对象的三种状态:

transient:瞬态或者自由态

new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 使用HibernateSession可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)


persistent:持久化状态

持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。


detached:脱管状态或者游离态

与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。

 

游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用 delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用 update()、saveOrUpdate()、lock()或者replicate()进行持久化。

7、Junit4 测试,代码如下:

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Date;

import learn.hibernate.bean.Person;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    SessionFactory factory = null;
    Session session = null;
    Transaction tx = null;
    
    /**
     * 测试之前初始化数据
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        System.out.println("---------初始化数据----------");
        
        Configuration config = new Configuration().configure();
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        factory = config.buildSessionFactory(sr);
        session = factory.openSession();
    }

    /**
     * 测试之后释放(销毁)数据
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        System.out.println("---------释放数据----------");
        if(session.isOpen()){
            session.close();
        }
    }

    @Test
    public void testPersist() {
        Person p = new Person("ass", 21, 123456, new Date());
        tx = session.beginTransaction();
        session.persist(p);
        tx.commit();
    }

}

创建 junit4 的测试类的时候如下图所示:

(查看:http://www.blogjava.net/TiGERTiAN/archive/2008/10/25/236519.html)

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。