【问题标题】:JPA can't update a dateJPA 无法更新日期
【发布时间】:2013-01-24 20:19:32
【问题描述】:

在我的 JavaEE 应用程序中,我使用 JPA 来存储我的数据。 但是我在更新存储在数据库中的日期时遇到了问题。当我想在我的应用程序中更改它时(以及当我合并时),所有字段都在更新,除了日期的... $ 你可以帮帮我吗 ?

这是我的实体:

package persistence
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
public class Event implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "NAME")
private String name;
@Column(name = "PLACE")
private String place;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "BEGINDATE")
private Date beginDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "ENDDATE")
private Date endDate;
@Column(name = "VISIBILITY")
private int visibility;
@Column(name = "DESCRIPTION")
private String description;

@OneToMany(mappedBy="relatedEvent")
private List<CustomizeEvent> customizedEvents;

@OneToOne(cascade = CascadeType.PERSIST,optional=false)
private Periodicity periodicity;

@ManyToOne(optional=false)
private UserAgenda eventOwner;

@ManyToMany
@JoinTable(name="EVENTS_BELONG_AGENDAS",joinColumns= @JoinColumn(name="EVENT_ID",referencedColumnName="ID"),inverseJoinColumns=@JoinColumn(name="AGENDA_ID",referencedColumnName="ID"))
private List<Agenda> belongToAgendas;

@ManyToMany
@JoinTable(name="EVENTS_GUESTS_AGENDAS",joinColumns= @JoinColumn(name="EVENT_ID",referencedColumnName="ID"),inverseJoinColumns=@JoinColumn(name="AGENDA_ID",referencedColumnName="ID"))    
private List<Agenda> guestToAgendas;

public Event() {
}

public Event(String name, String place, Date beginDate, Date endDate, int visibility, String description, Periodicity periodicity, UserAgenda eventOwner, Agenda agenda) {
    this.name = name;
    this.place = place;
    this.beginDate = beginDate;
    this.endDate = endDate;
    this.visibility = visibility;
    this.description = description;
    this.periodicity = periodicity;
    this.eventOwner = eventOwner;
    this.belongToAgendas = new ArrayList<Agenda>();
    this.belongToAgendas.add(agenda);
    this.customizedEvents = new ArrayList<CustomizeEvent>();
    this.guestToAgendas = new ArrayList<Agenda>();
}

public Event(String name, String place, Date beginDate, Date endDate, int visibility, String description, Periodicity periodicity, UserAgenda eventOwner, Agenda agenda,List<Agenda> guests) {
    this.name = name;
    this.place = place;
    this.beginDate = beginDate;
    this.endDate = endDate;
    this.visibility = visibility;
    this.description = description;
    this.periodicity = periodicity;
    this.eventOwner = eventOwner;
    this.belongToAgendas = new ArrayList<Agenda>();
    this.belongToAgendas.add(agenda);
    this.customizedEvents = new ArrayList<CustomizeEvent>();
    this.guestToAgendas = guests;
}


public Long getId() {
    return id;
}

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

public String getName() {
    return name;
}

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

public String getPlace() {
    return place;
}

public void setPlace(String place) {
    this.place = place;
}

public Date getBeginDate() {
    return beginDate;
}

public void setBeginDate(Date beginDate) {
    this.beginDate = beginDate;
}

public Date getEndDate() {
    return endDate;
}

public void setEndDate(Date endDate) {
    this.endDate = endDate;
}

public int getVisibility() {
    return visibility;
}

public void setVisibility(int visibility) {
    this.visibility = visibility;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public List<CustomizeEvent> getCustomizedEvents() {
    return customizedEvents;
}

public void setCustomizedEvents(List<CustomizeEvent> customizedEvents) {
    this.customizedEvents = customizedEvents;
}

public Periodicity getPeriodicity() {
    return periodicity;
}

public void setPeriodicity(Periodicity periodicity) {
    this.periodicity = periodicity;
}

public UserAgenda getEventOwner() {
    return eventOwner;
}

public void setEventOwner(UserAgenda eventOwner) {
    this.eventOwner = eventOwner;
}

public List<Agenda> getBelongToAgendas() {
    return belongToAgendas;
}

public void setBelongToAgendas(List<Agenda> belongToAgendas) {
    this.belongToAgendas = belongToAgendas;
}

public List<Agenda> getGuestToAgendas() {
    return guestToAgendas;
}

public void setGuestToAgendas(List<Agenda> guestToAgendas) {
    this.guestToAgendas = guestToAgendas;
}





@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 Event)) {
        return false;
    }
    Event other = (Event) 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 "persistence.Event[ id=" + id + " ]";
}

}

这是我在托管 bean 中调用的函数:

public void setNewEndDate(Event event, Date endDate) {
    Event e = em.find(Event.class, event.getId());
    e.setEndDate(endDate);
    e.setDescription("New description");
    em.persist(e);
}

【问题讨论】:

  • 当你说所有字段都在更新时,我很困惑。方法 setNewEndDate() 不更新除结束日期之外的任何其他字段。是否还有另一段代码需要您查看?
  • 是的,我还更新了描述字段 (e.setDescription("New description");),并且这个字段在数据库中正确更新。这就是为什么我不明白。
  • 在您的函数 setNewEndDate(Event event, Date endDate) 中,您正在使用persist(e)。尝试使用合并(e)。您还应该了解何时使用持久化和合并。尝试阅读此stackoverflow.com/questions/4509086/…

标签: java database jakarta-ee jpa


【解决方案1】:

如果您尝试更新的列上有updatable=false,问题也是一样的。

【讨论】:

    【解决方案2】:

    首先,最好提供一些有关事务管理的信息,因为它对于 JPA 的行为方式非常重要。

    这是我认为会发生的事情:

    您已经从 EntityManager 加载了 Event-object,它可能已从 session 中分离出来,因为当您执行 EntityManager#find 时您没有收到错误(您不能有 2 个具有相同 id 的对象一次在 EntityManager 中,你会得到一个异常..) 那么,你改变刚刚加载的附加对象的状态,并将它注册到 EntityManager 中(我不认为持久化的调用是正确的,或者在这里甚至是必要的..)但是,您的分离对象(作为参数发送的对象)仍然存在,并且尚未使用新值进行更新。因此,如果此对象在稍后被重新附加并保存(它可能由您明确执行,或者它可能在事务完成时自动发生),您最终将覆盖相关方法中设置的值。

    如果有的话,您在此处提供的方法可能(并且应该)如下所示:

    @Transactional
    public void setNewDate(final Integer eventId, final Date endDate() {
        final Event e = em.find(Event.class, eventId);
        e.setEndDate(endDate);
        //no need to explicitly save here, the changes will be saved when the transcation ends,
        //and the transaction will only last this method, as indicated by the @Transactional annotation.
    }
    

    但是,这仍然不是使用 JPA 的正确方法,通常你有一个存储库层,它处理基本的 CRUD 操作(查找、保存等),而在它之上的一层是逻辑层,它处理对象中值的实际更改。

    顺便说一句,你的 equals 和 hashcode 方法违反了这些方法的约定,因为 id 并不总是设置(一个新创建的尚未持久化的事件对象将没有一个 id),以及两个不同的新创建的 Event-尚未存储的对象,因此没有 id(除非你自己设置了 id,你真的不应该这样做),将被 equals 方法认为是相同的。

    【讨论】:

    • 好吧,它不起作用。我忘了说我使用 PrimeFaces 的日程安排,可能有一种冲突。
    • 我认为您在使用 JPA 时存在一些基本错误,您将 Event-object 作为参数传递,然后使用该对象的 id 执行 EntitiyManager#find 的事实告诉我,有些东西是没有做对。我不熟悉 PrimeFaces,但它可能内置了某种事务管理,通常每次调用服务器都会产生一个新事务,所以如果你先获取实体,然后调用 set 方法,你得到的实体首先将在事务(服务器请求)完成时存储,覆盖在 setNewDate 中所做的更改。
    • 抱歉我的错误,我是一名学生,对 JPA 不太熟悉。我会尝试找出错误,稍后可能会向您寻求帮助。
    • 一开始我也很难理解 JPA,但好在你只需要看到它正确完成一次就可以了解它应该如何工作的基本概念 :) 你做什么可以尝试不调用 setNewEndDate(),而只是在您现在作为参数传入的对象上设置新的 endDate。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    相关资源
    最近更新 更多