2014-09-23 3 views
4

я использовать JPA затмение TOPLINK & EJBJPA отключить автоматическое сохранение

каждый раз, когда я получить объект из базы данных, то изменить некоторые данные внутри него,

базы данных (MYSQL) автоматически менять тоже не предаю или сделать что-то

Пример:

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

я уже прочитал соответствующий вопрос здесь, но я до сих пор не могу понять его

я думаю, что я должен отделить сущность, но я не знаю, как это сделать, потому что

я класс GenericDAO генерируется из NetBeans

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) {} 

Это гарантирует, что транзакция не будет открыта, когда Дао передаст объект обратно на другой уровень. Любые изменения, которые вы вносите в объект, не будут синхронизированы с базой данных.

+0

где я должен разместить аннотацию сэр? в интерфейсе в классе реализации или в GenericDao? Я уже тестировал в интерфейсе, не работает, но я снова проверю –

+0

В классе реализации. – SJha

3

Понять это: «каждое обновление в прикрепленном объекте будет отражено в базе данных».

Когда предприятие прикреплено? Проще говоря, каждый объект, который проходит через EntityManager с помощью методов: persist, merge, refresh, delete (возможно, я забыл некоторые другие здесь) или в методах запроса (JPQL или find) внутри транзакции.

Посмотрите на примере ниже:

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

С собакой прошел методом находят внутри транзакции можно считать управление.

Если вы используете EJB, вы должны знать, что транзакция по умолчанию НЕОБХОДИМА. REQUIRED работает как: если транзакция открыта, давайте ее использовать. Если транзакция не открыта, откройте ее. (Это хороший парень)

Поскольку ваш метод не имеет индикатора для приостановки транзакции, каждое обновление в сущности будет отражено в базе данных. Что вы можете сделать? Используйте 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

+0

Ну, вы должны использовать Bean Manager Transaction. Вы будете управлять транзакцией вручную. – uaiHebert

Смежные вопросы