У меня есть 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();
Код: Выделить всё
**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**
Код: Выделить всё
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 обновить все поля (даже те, которые не меняются)?
Только в момент публикации этого сообщения сообщение, я понял возможное решение (не очень хорошее). Измените код перед обновлением, чтобы удалить объект из базы данных (сделав фиксацию), а затем запустите другую транзакцию, обновляя объект. Это значит, что объект снова удаляется и сохраняется. Оно работает.
Раньше я пробовал использовать методы удаления() и слияния() внутри одной транзакции, но это не сработало.>
Подробнее здесь: https://stackoverflow.com/questions/153 ... recognized
Мобильная версия