三、持久化对象
三、持久化对象
1.持久化类的要求
(1)提供一个无参数的构造器;
(2)提供一个标识属性(用来映射数据库表的主键字段,并不要使用基本数据类型);
(3)为持久化类的每个成员添加setter、getter方法;
(4)使用非final的类;
(5)重写equals()方法和hashCode()方法。
2.持久化对象的状态
Hibernate持久化对象支持如下几种对象状态:
1)瞬态:
对象由new操作符创建,且尚未与Hibernate Session关联的对象被认为处于瞬态;
2)持久化:
持久化实例在数据库中有对应的记录,并拥有一个持久化标识(identifier);
3)脱管:
某个实例曾经处于持久化状态,但随着与之关联的Session被关闭,该对象就变成脱管状态。
3.改变持久化对象状态的方法
持久化类News:
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="news_a_inf") public class News { @Id //主键标识 @GeneratedValue(strategy=GenerationType.IDENTITY) //主键增长策略 private Integer id; private String title; private String content; //setter getter方法 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
(1)持久化实体
示例:
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class Test { public static void main(String[] args) { //创建Configuration实例 Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); //以Configuration创建SessionFactory SessionFactory sf = cfg.buildSessionFactory(serviceRegistry); //创建Session Session session = sf.openSession(); //开启事务 Transaction tx = session.beginTransaction(); //新建一个持久化对象 News n1 = new News(); //对象处于瞬态 //设置news的属性值 n1.setTitle("news_a"); n1.setContent("this is test A!"); session.save(n1); //瞬态实体转变为持久化实体,把该实体对应记录插入到数据表中 //新建一个持久化对象 News n2 = new News(); //对象处于瞬态 n2.setTitle("news_b"); n2.setContent("this is test B!"); session.persist(n2); //瞬态实体转变为持久化实体,吧实体对应记录插入数据表中 //提交事务 tx.commit(); //关闭session session.close(); sf.close(); } }
save()方法和persist()方法的区别:
1)返回值,save()方法返回该持久化对象的标识属性值;persist()方法没有返回值;
2)程序执行save()方法将立即把持久化对象对应的记录插入到数据库中,而persist()方法则保证当它在一个事务外部时,并不立即转换成insert语句。
(2)根据主键加载持久化实体
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class Test2 { public static void main(String[] args) { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); SessionFactory sf = cfg.buildSessionFactory(serviceRegistry); Session session = sf.openSession(); Transaction t = session.beginTransaction(); //根据主键加载持久化实体 使用load()方法 News n1 = (News)session.load(News.class, 1); System.out.println(n1.getTitle()); System.out.println(n1.getContent()); //根据主键加载持久化实体 使用get()方法 News n2 = (News)session.get(News.class, 2); System.out.println(n2.getTitle()); System.out.println(n2.getContent()); } }
load()方法和get()方法的区别:
load()方法和get()方法的主要区别在于能否延迟加载,使用load()方法将具有延迟加载功能,load()方法不会立即访问数据库,当试图加载的记录不存在时,load()方法可能返回一个未初始化的代理对象;而get()方法总是立即访问数据库,如果数据库中并不存在查找内容,则直接返回null。
(3)更新持久化实体
一旦加载了该持久化实例后,该实体就处于持久化状态,在代码中对持久化实例所做的修改被保存到数据库。
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class Test3 { public static void main(String[] args) { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()) .build(); SessionFactory sf = cfg.buildSessionFactory(serviceRegistry); Session session = sf.openSession(); Transaction t = session.beginTransaction(); //根据实例标识属性加载持久化实例 News n = (News)session.load(News.class, 1); //修改属性值 n.setTitle("news_c"); n.setContent("this is test C!"); //直接修改后不需要session.flush();或者update()方法,修改就会被自动保存 //这是修改记录最简单的方法 t.commit(); session.close(); sf.close(); } }
(4)更新脱管实体
当程序修改脱管对象的状态后,应该显式地使用Session来保存这些修改。
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class Test4 { public static void main(String[] args) { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build(); SessionFactory sf = cfg.buildSessionFactory(serviceRegistry); //第一个Session Session s1 = sf.openSession(); //根据主键加载持久化实体 News n = (News)s1.load(News.class, 1); System.out.println(n.getTitle()); System.out.println(n.getContent()); //关闭Session s1.close(); //开启第二个Session Session s2 = sf.openSession(); //n曾处于持久化状态,session关闭后处于脱管状态 n.setTitle("test_a"); n.setContent("this is test A!"); //保存脱管对象所做的修改 s2.update(n); //也可以使用s2.merge(n)方法保存修改 } }
merge()方法和update()方法的区别:
当执行session.update(a)方法后,a对象将变成持久化状态;而执行session.merge(a)方法后,a对象任然不是持久化状态,a对象任然不会被关联到Session上,merge()方法返回的不是a对象,而是a对象的副本;
当程序使用merge()方法保存程序对脱管对象所做的修改时,如果Session中存在相同持久化标识的持久化对象,merge()方法里提供的对象状态将覆盖原有持久化实例的状态。如果Session中没有相应的持久化实例,则尝试从数据库中加载,或者创建新的持久化实例,最后返回该持久化实例。
(5)删除持久化实体
通过Session的delete()方法可以删除持久化实例,一旦删除了该持久化实例,该持久化实例对应的数据表记录也将会被删除。
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class Test5 { public static void main(String[] args) { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()) .build(); SessionFactory sf = cfg.buildSessionFactory(serviceRegistry); Session session = sf.openSession(); Transaction t = session.beginTransaction(); //加载持久化实体 News n = (News) session.load(News.class, 1); //删除该实体 session.delete(n); t.commit(); session.close(); sf.close(); } }