2014-09-23 101 views
4

我使用JPA日食Toplink的& EJBJPA禁用自动保存

每次我收到来自数据库实体然后改变它里面的一些数据,

数据库(MySQL的)全自动改得没有我承诺或做一些事情

例子:

Player p = em.findById(1); 
p.setName(newName); 
// i do nothing , but database automaticly change 

我已经在这里阅读相关的问题,但我仍然无法弄清楚

我想我必须分离的实体,但我不知道如何做到这一点,因为

我从NetBeans的

GenericDAO生成的类GenericDAO(产生从netbeans的)

public abstract class GenericDAO<T> { 
    private Class<T> entityClass; 

    public GenericDAO(Class<T> entityClass) { 
     this.entityClass = entityClass; 
    } 

    protected abstract EntityManager getEntityManager(); 

    public void insert(T entity) { 
     getEntityManager().persist(entity); 
    } 

    public void edit(T entity) { 
     getEntityManager().merge(entity); 
    } 

    public void delete(T entity) { 
     getEntityManager().remove(getEntityManager().merge(entity)); 
    } 

    public T findById(Object id) { 
     return getEntityManager().find(entityClass, id); 
    } 

    public List<T> findAll() { 
     javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
     cq.select(cq.from(entityClass)); 
     return getEntityManager().createQuery(cq).getResultList(); 
    } 

    public List<T> findRange(int[] range) { 
     javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
     cq.select(cq.from(entityClass)); 
     javax.persistence.Query q = getEntityManager().createQuery(cq); 
     q.setMaxResults(range[1] - range[0] + 1); 
     q.setFirstResult(range[0]); 
     return q.getResultList(); 
    } 

    public int count() { 
     javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
     javax.persistence.criteria.Root<T> rt = cq.from(entityClass); 
     cq.select(getEntityManager().getCriteriaBuilder().count(rt)); 
     javax.persistence.Query q = getEntityManager().createQuery(cq); 
     return ((Long) q.getSingleResult()).intValue(); 
    } 

} 

DaoPlayer

@Local 
public interface DaoPlayer{ 
    void insert(Player player); 

    void edit(Player player); 

    void delete(Player player); 

    Player findById(Object id); 

    List<Player> findAll(); 

    List<Player> findRange(int[] range); 

    int count(); 

ImplPlayer

@Stateless 
public class ImplPlayer extends GenericDAO<Player> implements DaoPlayer{ 
    @PersistenceContext(unitName = "MonsterPuzzle") 
    private EntityManager em; 

    @Override 
    protected EntityManager getEntityManager() { 
     return em; 
    } 

    public ImplPlayer() { 
     super(Player.class); 
    } 

} 

我的问题是

  • 如何禁用JPA全自动保存到数据库?
  • (因为我认为我需要分离)如何从GenericDAO分离实体?

回答

2

您将需要了解如何管理应用程序中的事务。考虑你的方法之一:

Player findById(Object id){} 

如果您使用的是Java EE环境容器管理事务,你只需要标记事务作为DAO不支持。

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
Player findById(Object id) {} 

当Dao将实体传递回不同的层时,这将确保事务未打开。您对实体所做的任何更改都不会与数据库同步。

+0

我应该在哪里放置标注先生?在实现类中或GenericDao中的接口?我已经在界面上测试过了,但我会再次检查 – 2014-09-23 01:00:45

+0

在实现类中。 – SJha 2014-09-23 01:24:33

3

了解此:“附件中的每个更新都将反映在数据库中”。

当一个实体连接?简单来说,每一个通过EntityManager通过EntityManager持久化,合并,刷新,删除(也许我忘记了其他一些)或者在事务中的查询(JPQL或find)方法的实体。

看看下面的例子:

entityManager.getTransaction().begin(); 
Dog dog = entityManager.find(Dog.class, 1); 
dog.setGoodBoyLevel(99); 
entityManager.getTransaction().commit(); 

因为狗通过它可以被视为管理的事务中find方法传递。

如果您使用EJB,您必须知道默认事务是必需的。要求的工作如下:如果有交易开放,让我们使用它。如果没有开放交易,让我们打开它。 (这是一个不错的人)

由于你的方法没有任何指示器来暂停事务,实体中的每个更新都会反映在数据库中。你能做什么?由于您使用的是NOT_SUPPORTED交易选项

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
public void yourMethod(){ 
    // to awesome things 
} 

你的实体将分离:使用NOT_SUPPORTED交易方式。 分离是什么意思? JPA不会分析实体中的更新。如果你只是想读一些信息,那没关系。但下面的代码会引发异常:

entityManager.getTransaction().begin(); 
Dog dog = new Dog(); 
Owner owner = getDetachedOwner(ownerId); 
dog.setOwner(owner); 
entityManager.persist(dog); 
entityManager.getTransaction().commit(); 

这里的问题是,所有者是分离的,所以JPA不知道它会引发异常。

请注意NOT_SUPPORTED选项。 [=

+0

是否没有通用的方法来禁用自动保存的这种行为?我不想错过事务上下文,但只想显式保存更改 – Simon 2017-08-10 06:17:56

+0

那么,你应该使用Bean Manager Transaction。您将手动控制交易。 – uaiHebert 2017-08-17 08:22:53