JPA merge() обновляет только некоторые поля. Другие изменения не распознаютсяJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 JPA merge() обновляет только некоторые поля. Другие изменения не распознаются

Сообщение Anonymous »

Это мой первый пост. Итак, я надеюсь, что вопрос интересен.
У меня есть Java-программа, которая использует Swing+JPA для работы с базой данных
PostgreSQL. В качестве поставщика сохраняемости я использую EclipseLink JPA 2.0. Мой класс сущностей был автоматически
сгенерирован Netbeans 7.2.1

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

Я пробовал несколько способов обойти эту проблему: я пытался изменить параметры, связанные со стратегией синхронизации моего постоянного модуля, изменить положение строки в коде (по мере обновления других полей), я также пытался добавить в поле Entity Class аннотацию @Basic(optional = false). Любая из моих попыток сработало.

Вот код моего класса сущности (Senha.java):

Код: Выделить всё

package model;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;

/**
*
* @author Diego Dias
*/
@Entity
@Table(name = "senha")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Senha.findAll", query = "SELECT s FROM Senha s"),
@NamedQuery(name = "Senha.findById", query = "SELECT s FROM Senha s WHERE s.id = :id"),
@NamedQuery(name = "Senha.findByGuiche", query = "SELECT s FROM Senha s WHERE s.guiche = :guiche"),
@NamedQuery(name = "Senha.findByStatus", query = "SELECT s FROM Senha s WHERE s.status = :status"),
@NamedQuery(name = "Senha.findByHchamada", query = "SELECT s FROM Senha s WHERE s.hchamada = :hchamada"),
@NamedQuery(name = "Senha.findByAtendente", query = "SELECT s FROM Senha s WHERE s.atendente = :atendente"),
@NamedQuery(name = "Senha.findByHcriacao", query = "SELECT s FROM Senha s WHERE s.hcriacao = :hcriacao"),
@NamedQuery(name = "Senha.findByDtcriacao", query = "SELECT s FROM Senha s WHERE s.dtcriacao = :dtcriacao"),
@NamedQuery(name = "Senha.findByNumeracao", query = "SELECT s FROM Senha s WHERE s.numeracao = :numeracao"),
@NamedQuery(name = "Senha.findByNchamadas", query = "SELECT s FROM Senha s WHERE s.nchamadas = :nchamadas"),
@NamedQuery(name = "Senha.findByPainel", query = "SELECT s FROM Senha s WHERE s.painel = :painel"),
@NamedQuery(name = "Senha.findMaxNumeracaoByDtcriacao", query = "SELECT MAX(s.numeracao) FROM Senha s WHERE s.dtcriacao = :dtcriacao"),
@NamedQuery(name = "Senha.findByStatusAndHchamadaAndHcriacao",  query = "SELECT s FROM Senha s WHERE s.status = :status AND s.hchamada = :hcriacao")})
public class Senha implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "guiche")
private String guiche;
@Column(name = "status")
private Character status;
@Column(name = "hchamada")
@Temporal(TemporalType.TIME)
private Date hchamada;
@Column(name = "atendente")
private Integer atendente;
@Column(name = "hcriacao")
@Temporal(TemporalType.TIME)
private Date hcriacao;
@Column(name = "dtcriacao")
@Temporal(TemporalType.DATE)
private Date dtcriacao;
@Column(name = "numeracao")
private Integer numeracao;
@Column(name = "nchamadas")
private Integer nchamadas;
@Column(name = "painel")
private Boolean painel;

public Senha() {
}

public Senha(Integer id) {
this.id = id;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getGuiche() {
return guiche;
}

public void setGuiche(String guiche) {
this.guiche = guiche;
}

public Character getStatus() {
return status;
}

public void setStatus(Character status) {
this.status = status;
}

public Date getHchamada() {
return hchamada;
}

public void setHchamada(Date hchamada) {
this.hchamada = hchamada;
}

public Integer getAtendente() {
return atendente;
}

public void setAtendente(Integer atendente) {
this.atendente = atendente;
}

public Date getHcriacao() {
return hcriacao;
}

public void setHcriacao(Date hcriacao) {
this.hcriacao = hcriacao;
}

public Date getDtcriacao() {
return dtcriacao;
}

public void setDtcriacao(Date dtcriacao) {
this.dtcriacao = dtcriacao;
}

public Integer getNumeracao() {
return numeracao;
}

public void setNumeracao(Integer numeracao) {
this.numeracao = numeracao;
}

public Integer getNchamadas() {
return nchamadas;
}

public void setNchamadas(Integer nchamadas) {
this.nchamadas = nchamadas;
}

public Boolean getPainel() {
return painel;
}

public void setPainel(Boolean painel) {
this.painel = painel;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Senha)) {
return false;
}
Senha other = (Senha) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "model.Senha[ id=" + id + " ]";
}

}
Вот соответствующий код метода, который обновляет мой объект. Код внутри... не влияет на объект.

Код: Выделить всё

EntityManagerFactory emf = ctrlCreateEntityManager();
EntityManager em = emf.createEntityManager();

...

current = em.find(Senha.class, getCurrentId());
if (current.getStatus().equals('W')) {
em.getTransaction().begin();
current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
current.setHchamada(Calendar.getInstance().getTime());
current.setNchamadas(current.getNchamadas() + 1);
current.setPainel(true);
em.merge(current);
em.getTransaction().commit();
frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
}
...
em.close();
emf.close();
Когда я просматриваю базу данных, поля Статус Хчамада, Нчамадас обновляются, но поле Painel (логического типа) не обновляется. Следуйте за мной. Я представляю отрывок из журнала JPA/EclipseLink:

Код: Выделить всё

**begin transaction**

**[EL Fine]**:
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])--UPDATE senha SET
hchamada = ?, nchamadas = ? WHERE (id = ?)
bind => [02:15:49, 2, 4]

**[EL Finer]**:
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])

**commit transaction**
Просматривая код, я поставил if перед изменением значения, чтобы проверить, имеет ли объект, управляемый JPA, уже значение, которое я хочу установить. Вот измененный код:

Код: Выделить всё

EntityManagerFactory emf = ctrlCreateEntityManager();
EntityManager em = emf.createEntityManager();

...

current = em.find(Senha.class, getCurrentId());
if (current.getStatus().equals('W')) {
em.getTransaction().begin();
current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
current.setHchamada(Calendar.getInstance().getTime());
current.setNchamadas(current.getNchamadas() + 1);
if (current.getPainel()) {
System.out.println("Painel is already true");
}
current.setPainel(true);
em.merge(current);
em.getTransaction().commit();
frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
}
...
em.close();
emf.close();
Когда я запускаю код, я получил сообщение, указывающее, что для моей сущности уже установлено значение, которое я хочу записать в базу данных. Итак, я думаю, что JPA/EclipseLink не обновляет значение, если оно не изменяется по отношению к управляемому им классу сущности. Однако перед запуском кода я вручную обновил поле Painel в базе данных до значения false. ТОГДА:
  • Я не понял, почему это обновление не распознается при получении объекта.
  • Как заставить JPA обновить все поля (даже те, которые не меняются)?
ВОЗМОЖНОЕ (НЕ ТАК ХОРОШЕЕ) РЕШЕНИЕ:

Только в момент публикации этого сообщения сообщение, я понял возможное решение (не очень хорошее). Измените код перед обновлением, чтобы удалить объект из базы данных (сделав фиксацию), а затем запустите другую транзакцию, обновляя объект. Это значит, что объект снова удаляется и сохраняется. Оно работает.

Раньше я пробовал использовать методы удаления() и слияния() внутри одной транзакции, но это не сработало.>

Подробнее здесь: https://stackoverflow.com/questions/153 ... recognized
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»