2013-10-11 3 views
11

Давайте предположим, что у меня есть этот класс:Получения поля объекта предыдущего значения зимует JPA

@EntityListeners({MyListener.class}) 
class MyClass { 
    String name; 
    String surname; 

    public String getName() { 
    return name; 
    } 

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

    public String getSurname() { 
    return name; 
    } 

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

    public void save() { 
    JPA.em().persist(this); 
    return this; 
    } 

    public void update() { 
    JPA.em().merge(this); 
    } 

    public static MyClass findById(Long id) { 
    return JPA.em().find(MyClass.class, id); 
    } 
} 

Теперь в моем MyListener классе я пытаюсь выяснить, предыдущий экземпляр значения MyClass по сравнению с новым значением, которое собирается получить сохранен (обновлен) в базу данных. Я делаю это с preupdate metdhod:

@PreUpdate 
public void preUpdate(Object entity) { 
...some logic here...unable to get the old object value in here   
} 

Так предполагая, у меня есть экземпляр MyClass объектов с именем и фамилией:

MyClass mycls = new MyClass(); 
mycls.setName("Bob"); 
mycls.setSurname("Dylan"); 
mycls.save(); 

Это не было подобрано слушателем, который хорошо, потому что я слушаю только для обновлений. Теперь, если бы я, чтобы обновить этот экземпляр так:

MyClass cls = MyClass.findById(someLongId) 
cls.setSurname("Marley"); 
cls.update(); 

Таким образом, это вызывает метод preUpdate в mylistener и когда я пытаюсь:

MyClass.findById(someLongId); 

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

Как получить значение из базы данных в моем методе preUpdate, а не том, который я только что обновил?

ответ

18

Я думаю, что простой способ - сохранить предыдущее значение в переходной переменной, что JPA не будет сохраняться. Итак, просто введите переменную previousSurname и сохраните фактическое значение, прежде чем перезаписывать его в установщике.

Если вы хотите сохранить несколько свойств, было бы легко, если ваш класс MyClass является Serializable.

Если да добавить слушателя после нагрузки

public class MyClass implements Serializable { 

    @Transient 
    private transient MyClass savedState; 

    @PostLoad 
    private void saveState(){ 
     this.savedState = SerializationUtils.clone(this); // from apache commons-lang 
    } 

} 

Но следует помнить, что savedState является отдельно стоящий экземпляр ,

После этого вы можете получить доступ к предыдущему состоянию в своем EntityListener.

Вы также можете переместить слушателя PostLoad на класс EntityListener. Но тогда вам нужен доступ к полю savedState. Я рекомендую сделать это либо пакет или использовать область видимости пакет область действия аксессор и положить MyClass и MyListener в том же пакете,

public class MyListener { 

    @PostLoad 
    private void saveState(MyClass myClass){ 
     myClass.saveState(SerializationUtils.clone(myClass)); // from apache commons-lang 
    } 

} 

public class MyClass implements Serializable { 

    @Transient 
    private transient MyClass savedState; 

    void saveState(MyClass savedState){ 
     this.savedState = savedState; 
    } 

} 
+0

Привет Рене, я не @PostLoad в моем классе POJO. У меня это внутри моего слушателя сущности –

+0

Хорошо, вы можете переместить код в прослушиватель объектов. Я имею в виду, что EntityListener создает копию объекта при загрузке и задает поле. Или есть что-то, что я пропустил? –

+0

, но если я переведу этот код в класс слушателя, изменяется экземпляр прослушивателя. поэтому, если я устанавливаю значение для экземпляра listener в postload, этот экземпляр имеет значение null в preupdate –

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