首页 > 代码库 > Hibernate学习---第二节:hibernate 增、删、改、查

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

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

/** * 数据保存 * 1、save() * 2、persist() */@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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")@Testprivate 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 的测试类的时候如下图所示:

QQ截图20141204203428

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

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