2011-05-03 2 views
1

Я совершенно не знаком с JPA + Hibernate + Spring (но у меня довольно много опыта с платформой Spring для веб-приложения и SQL), поэтому мой вопрос здесь может не использовать правильный технический термин в JPA.Сохранять значение объекта, когда оно установлено

У меня есть типичный User POJO, который аннотируется javax.persistence.*, и я установил hibernate + hsqldb в соответствии с приведенными мной примерами, которые в настоящее время работают нормально. User класса выглядит следующим образом:

@Entity 
@Table(name = "USER") 
public class User { 

    private Long id; 
    private String name; 
    // Ignore id getter and setter methods 

    @Column(name = "USER_NAME") 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

Это мой UserDAOImpl класса.

public class UserDAOImpl implements UserDAO { 

    private HibernateTemplate hibernateTemplate; 

    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.hibernateTemplate = new HibernateTemplate(sessionFactory); 
    } 

    @Override 
    public void saveUser(User user) { 
     hibernateTemplate.saveOrUpdate(user); 
    } 

    // This method is made to return only one User object. 
    @Override 
    @SuppressWarnings("unchecked") 
    public User getGiUser() { 
     return hibernateTemplate.find("from User where User_Name ='gi'").get(0); 
    } 
} 

Используя getGiUser метод, я могу получить постоянный объект из базы данных (если я правильно понимаю). Мой вопрос заключается в том, можно ли сделать метод User.setName() немедленно передать в базу данных, когда он вызывается, не сохраняя его вручную? Как и где я должен начать или узнать об этом?

ответ

1

Из того, что я видел, что вы ищете сервис боба, который вызывает UserDAO:

public class UserServiceImpl implements UserService { 
    private UserDAO userDao; // injected by Spring 

    @Transactional 
    public void changeUserName(String name) { 
     User user = userDao.getGiUser(); 
     user.setName(name); 
     // I can't remember if this saveUser() call is required, or if 
     // Hibernate will automatically pick up the changes and save the 
     // user object 
     userDao.saveUser(user); 
    } 
} 

@Transactional приходит отсюда:

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/transaction.html

Кроме того, использование HibernateTemplate не является предпочтительным способом использования Hibernate. Эта часть Весенних документации показывает, как использовать прямой Hibernate код:

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/orm.html

Вы на самом деле предпочитают использовать Hibernate в качестве поставщика JPA 2 с весны, однако; глава ORM (см. выше) также показывает, как интегрировать JPA с Spring. Hibernate все еще может оставаться вашим провайдером JPA 2. Таким образом, вы отделите весь свой код от Spring и Hibernate и просто используйте стандартные аннотации JPA 2 с EntityManager.

+0

Использует ли EntityManager транзакционную фиксацию? Причина, по которой я спросил, потому что я использовал openrdf-sesame со своим менеджером сущностей. Все изменения в объекте сущности немедленно сохраняются в тройном хранилище. Поэтому я задаюсь вопросом, есть ли такая же концепция в JPA. – gigadot

+0

+1 за предложение об использовании EntityManager и об использовании HibernateTemplate не является предпочтительным методом. – gigadot

+0

@gigadot: Да, вы можете указать транзакционные блоки с JPA 2. Это другая аннотация, хотя, IIRC. Кроме того, имейте в виду, что я лично не пробовал JPA 2 по весне, используя Hibernate в качестве поставщика непрерывности, но я бы скорее использовал это прямо сейчас, чем «устаревший» код HibernateTemplate, который у меня есть сейчас. – BobG

1

Для этого вы можете использовать механизм перехвата. Истина заключается в том, что изменение должно быть сохранено где-то вдоль линии, но ваш класс User не подходит для этого, поэтому вы можете написать код в другом месте и использовать механизм перехвата или Aspect Oriented с использованием инфраструктуры приложения, например Spring, для контроля методы, вызываемые и всякий раз, когда вызывается конкретный метод (например, setName), сохраняющий состояние вашего класса.

Вот an example из спящего режима и яровой интеграции

+0

+1 использование AOP может быть вариантом для меня. – gigadot

1

Когда вы получите пользователя из сеанса (с session.get(), session.load(), ассоциации обходом или HQL или критерии запроса), любое изменение пользователю будет совершено, когда (без звонка на номер save, update, saveOrUpdate или merge). Он не будет немедленно записываться в базу данных (краснеть), но будет при необходимости: до фиксации или до выполнения запроса, результат которого может зависеть от флеша. Вам, как правило, не нужно заботиться.

Если «привязано к базе данных» означает «совершенное с точки зрения транзакционного фиксации», тогда это невозможно. Изменения совершаются, когда совершается окружающая транзакция.

Если вы хотите, чтобы определенное обновление было совершено за пределами текущей транзакции, вам необходимо сделать обновление в другой транзакции, используя код, такой как ответ в BobG, но аннотированный с помощью @Transactional(propagation = Propagation.REQUIRES_NEW).

Возможно, вам стоит больше узнать, что вы хотите, и почему вы хотите это сделать.

+0

Я относительно новичок в JPA, поэтому я до сих пор не совсем понимаю, что вы подразумеваете под «когда совершается окружающая транзакция». И да, я имел в виду, что значения должны быть привязаны к реляционной таблице. если возможно, я могу уменьшить сложность кодирования (никаких дополнительных изменений или обновлений, которые мне нужно позаботиться). – gigadot

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