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