JPA实体状态分析java
实体状态详解docker
实际上就是new了一个普通的JavaBean对象。
1.当1.瞬时对象调用了管理器的persist()后,便可将通常的JavaBean作为了持久Bean,该Bean的任何属性改动都会牵涉到数据库记录的改动。
2.一旦该记录flush到数据库以后,而且事务提交了,那么此对象不在持久化上下文中,即:变为了游离(没人管的孩子)状态了。
在游离状态的时候调用更新、刷新方法后,游离状态对象就变为了在持久化上下文的托管状态了。
3.经过管理器的find方法,将实体从数据库查询出来后,该实体也就变为了托管形态。
持久化状态:数据库
当处在托管状态的实体Bean被管理器flush了,那么就在极短暂的时间进入了持久化状态,事务提交以后,马上变为了游离状态。
您能够把持久化状态当作实实在在的数据库记录。
游离状态就是提交到数据库后,事务commit后实体的状态,由于事务已经提交了,此时实体的属性任你如何改变,也不会同步到数据库,
由于游离是没人管的孩子,不在持久化上下文中。
通常要删除一个持久化对象的时候都是先find出来,以后调用remove方法删之,此时这个对象就是销毁对象,实际上就是瞬时对象的另外一种形态罢了。
EntityManager一些经常使用的API(包含query, insert, update, delete操做)缓存
1)get entity —— find() or getReference()服务器
Person person = em.find(Person.class,1);
2)insert —— persist()网络
Person person = new Person();
person.setName(name);
//把数据保存进数据库中
em.persist(person);
3)update —— 分2种状况
状况1:当实体正在被容器管理时,你能够调用实体的set方法对数据进行修改,在容器决定flush时(这个由Container自行判断),更新的数据 才会同步到数据库,而不是在调用了set方法对数据进行修改后立刻同步到数据库。若是你但愿修改后的数据立刻同步到数据库,你能够调用EntityManager.flush()方法。session
public void updatePerson() {
try {
Person person = em.find(Person.class, 1);
person.setName("lihuoming"); //方法执行完后便可更新数据
} catch (Exception e) {
e.printStackTrace();
}
}
状况2:在实体Bean已经脱离了EntityManager的管理时,你调用实体的set方法对数据进行修改是没法同步更改到数据库的。你必须调用 EntityManager.merge()方法。调用以后,在容器决定flush时(这个由container自行判断),更新的数据才会同步到数据 库。若是你但愿修改后的数据立刻同步到数据库,你能够调用EntityManager.flush()方法。性能
public boolean updatePerson(Person person) {
try {
em.merge(person);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
下面的代码会调用上面的方法。由于下面的第二行代码把实体Bean 返回到了客户端,这时的实体Bean已经脱离了容器的管理,在客户端对实体Bean进行修改,最后把他返回给EJB 容器进行更新操做:编码
PersonDAO persondao = (PersonDAO) ctx.lookup("PersonDAOBean/remote");
Person person = persondao.getPersonByID(1); //此时的person 已经脱离容器的管理
person.setName("张小艳");
persondao.updatePerson(person);
在这种状况下,调用merge方法,将返回一个新的对象(有id),并对这个新的对象执行insert操做。
在这种状况下,调用merge方法,将返回一个新的对象,并对该对象执行insert操做。
新对象的id是数据库中这条记录的id(好比自增加的id),而不是咱们本身传入的id。(其实和状况1的结果是同样的)
在这种状况下,调用merge方法,将会从数据库中查询对应的记录,生成新的对象,而后将咱们传入的对象复制到新的对象,最后执行update操做。
简单来讲,就是更新操做
在这种状况下,调用merge方法,JPA会把传入的对象赋值到entityManager的缓存中的对象,而后对entityManager缓存中的对象执行update操做。
(和状况3的结果同样)
4)Delete —— Remove().net
Person person = em.find(Person.class, 2);
//若是级联关系cascade=CascadeType.ALL,在删除person 时候,也会把级联对象删除。
//把cascade属性设为cascade=CascadeType.REMOVE 有一样的效果。
em.remove (person);
Order order = new Order();
order.setId(140);
entityManager.remove(order);
上面这段代码会抛出异常,由于order是咱们本身建立的对象,也就是游离对象。必须这样写:
Order order = new Order();
order = entityManager.find(Order.class, 140);
entityManager.remove(order);
这段代码中的order是从数据库中获取的,也就是持久化对象
hibernate的delete()方法,只要对象有Id,就能够删除
5)HPQL query —— createQuery()
除了使用find()或getReference()方法来得到Entity Bean以外,你还能够经过JPQL获得实体Bean。
Query query = em.createQuery("select p from Person p where p. name=’黎明’");
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//处理Person
}
…
Query query = em.createQuery("update Person as p set p.name =?1 where p. personid=?2");
query.setParameter(1, “黎明”);
query.setParameter(2, new Integer(1) );
int result = query.executeUpdate(); //影响的记录数
…
Query query = em.createQuery("delete from Person");
int result = query.executeUpdate(); //影响的记录数
6)SQL query —— createNaiveQuery()
//咱们可让EJB3 Persistence 运行环境将列值直接填充入一个Entity 的实例,
//并将实例做为结果返回.
Query query = em.createNativeQuery("select * from person", Person.class);
List result = query.getResultList();
if (result!=null){
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
Person person= (Person)iterator.next();
… ..
}
}
…
Query query = em.createNativeQuery("update person set age=age+2");
query.executeUpdate();
7)Refresh entity —— refresh()
Order order= entityManager.find(Order.class, 170);
order= entityManager.find(Order.class, 170);
Order order= entityManager.find(Order.class, 170);
entityManager.refresh(order);
Person person = em.find(Person.class, 2);
//若是此时person 对应的记录在数据库中已经发生了改变,
//能够经过refresh()方法获得最新数据。
em.refresh (person);
8)Check entity是否在EntityManager管理当中 —— contains()
Person person = em.find(Person.class, 2);
。。。
if (em.contains(person)){
//正在被持久化内容管理
}else{
//已经不受持久化内容管理
}
9)分离全部当前正在被管理的实体 —— clear()
10)将实体的改变马上刷新到数据库中 —— flush()
例子1:在方法返回时才提交事务
public void updatePerson(Person person) {
try {
Person person = em.find(Person.class, 2);
person.setName("lihuoming");
em.merge(person);
//后面还有众多修改操做
} catch (Exception e) {
e.printStackTrace();
}
//更新将会在这个方法的末尾被提交和刷新到数据库中
}
若是你须要在事务提交以前将更新刷新到数据库中,你能够直接地调用EntityManager.flush()方法。
这种状况下,你能够手工地来刷新数据 库以得到对数据库操做的最大控制。
public void updatePerson(Person person) {
try {
Person person = em.find(Person.class, 2);
person.setName("lihuoming");
em.merge(person);
em.flush();//手动将更新马上刷新进数据库
//后面还有众多修改操做
} catch (Exception e) {
e.printStackTrace();
}
}
11)改变实体管理器的Flush模式 —— setFlushMode()
entityManager.setFlushMode(FlushModeType.COMMIT);
刷新在查询语句执行前(除了find()和getreference()查询)或事务提交时才发生,
使用场合:在 大量更新数据的过程当中没有任何查询语句(除了find()和getreference()查询)的执行。
刷新只有在事务提交时才发生,
使用场合:在大量更新数据的过程当中存在查询语句(除了find()和 getreference()查询)的执行。
JDBC 性能最大的增进是减小JDBC 驱动与数据库之间的网络通信。
FlushModeType.COMMIT模式使更新只在一次的网络交互中完成,而FlushModeType.AUTO 模式可能须要屡次交互(触发了多少次Flush 就产生了多少次网络交互)
12)获取持久化实现者的引用 —— getDelegate()
HibernateEntityManager manager = (HibernateEntityManager)em.getDelegate();
13)判断当前的实体管理器是不是打开状态--isOpen ()
14)返回资源层的事务对象。EntityTransaction实例能够用于开始和提交多个事务--getTransaction ()
15)大量数据分批提交
有的时候咱们须要循环保存数据,当保存大量数据的时候,
若是到最后才提交全部数据,那么数据库的负载可能会比较大。咱们能够这样作,每30个记录就提交(flush)一次。
代码以下(每到30条记录的时候就强制提交):
public void updateBatch(List<Z> list) {
for (int i = 0; i < list.size(); i++) {
entityManager.merge(list.get(i)); //变成托管状态
if (i % 30 == 0) {
entityManager.flush(); //变成持久化状态
entityManager.clear(); //变成游离状态
}
}
}
public void saveBatch(List<Z> list) {
for (int i = 0; i < list.size(); i++) {
entityManager.persist(list.get(i)); //变成托管状态
if (i % 30 == 0) {
entityManager.flush(); //变成持久化状态
entityManager.clear(); //变成游离状态
}
}
}
参考来源: http://blog.csdn.net/fobdddf/article/details/19479073
参考来源: http://blog.csdn.net/dufufd/article/details/54408727
参考来源:http://toknowme.iteye.com/blog/2235981