【问题标题】:Unable to figure out the object in same identifier value in Spring-boot无法在 Spring-boot 中找出具有相同标识符值的对象
【发布时间】:2021-07-09 16:27:46
【问题描述】:

“trace”:“org.springframework.dao.DataIntegrityViolationException:具有相同标识符值的不同对象已与会话关联:[com.ffcalendar.calendarDemo.models.User#1];嵌套异常是 javax。 persistence.EntityExistsException:具有相同标识符值的不同对象已与会话关联:[com.ffcalendar.calendarDemo.models.User#1]\r\n\tat org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible( EntityManagerFactoryUtils.java:400)\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235)\r\n\tat org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible( AbstractEntityManagerFactoryBean.java:551)\r\n\tat org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n\tat org.springframework.dao.support.DataA ccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n\tat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)\r\n\tat

【问题讨论】:

  • 您的实体是否有正确的equalshashCode 实现?
  • 是的,不是针对所有字段,而是必要的字段。
  • @ShreyashSharma 与我们分享进行这些保存的代码

标签: java spring spring-boot rest


【解决方案1】:

"已存在具有相同标识符值的不同对象 与会话相关联”

在持久性上下文中只允许 1 个具有特定 ID 的托管实例。这意味着对于特定类,您只能拥有 1 个实例,例如 id =322,它被认为处于 JPA 的托管状态。如果您有来自同一类的另一个具有相同 Id 的分离实例,并且您尝试重新附加它,那么您会收到您遇到的错误。

如果您提供有关如何保存这些实体的更多信息,我们将能够找出问题所在。

但根本原因就是我所描述的。

编辑:在问题中提供更多信息后

我有很多怀疑,因为你的代码看起来不是很干净,但无论如何我都会从显而易见的开始

public class CalendarEvent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

     @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((eventDateTime == null) ? 0 : eventDateTime.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            CalendarEvent other = (CalendarEvent) obj;
            if (eventDateTime == null) {
                if (other.eventDateTime != null)
                    return false;
            } else if (!eventDateTime.equals(other.eventDateTime))
                return false;
            return true;
        }
     }

在此处查看您的这部分代码。对于 JPA,您已声明将使用 Long id 区分实体。

不过,稍后您提供一个 equals 和一个仅考虑 eventDateTime 的 hashcode 方法。

所以一个包含 CalendarEvents 的列表可以有多个具有相同 id 和不同 eventDateTime 的 CalendarEvents。这对 JPA 来说绝对是错误的。

首先实现只考虑 Long id 字段的 equals 和 hashcode。如果这不是具体的根本原因,我们会更进一步,但考虑到您使用 CalendarEvents 的方式,这肯定会有所改变

old_events = user.getEvents(); //DB fetch
old_events.addAll(new_events);
Set<CalendarEvent> set_event = new HashSet<CalendarEvent>(old_events);

在这里,您会受到错误的哈希码和等号的影响。 您尝试过滤一组独特的事件。但是该集合将仅保留具有唯一 eventDateTime 的事件。 考虑到在您的代码中,您在集合中添加了 2 次相同的元素,它们中的大多数将具有相同的 id。

在持久化的后期,JPA 预计不会出现这种情况。

【讨论】:

  • 我已经为相关文件添加了完整的代码。希望这会有所帮助。
【解决方案2】:

一个用户可以参加许多活动。 一个事件可以有很多用户。 所以它将是@ManyToMany 映射。 只使用两个表 Calendrevent 和 User

用户:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String name;
    @ManyToMany
    @JoinTable( name ="user_events", joinColume = @JoinColume(name = "user_id"), inverseJoinColume = @JoinColume(name = "event_id"))
    private List<Event> events = new ArrayList<>();

事件:

@Entity
public class Event {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;    
    private String title;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime eventDateTime;
    @ManyToMany(mappedBy = "events")
    private List<User> users = new ArrayList<>();

在用户实体中添加每个事件后保存用户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 2020-08-03
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 2012-08-23
    • 2020-10-12
    相关资源
    最近更新 更多