NullPointerException 尝试更新包含带有版本字段的枢轴 table 的实体

NullPointerException trying to update an entity that contain a pivot table with version field

我正在尝试通过作为集合存在的实体更新数据透视表 table,我的数据透视表 table 有一个版本字段,当它更新时抛出 NullPointerException

我正在使用 Java 8 和 Hibernate 作为 JPA 提供程序

主要实体 "Carpeta.java"

@JoinColumn(name = "car_subcarpeta_id", referencedColumnName = "sub_id")
    @OneToOne(cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    private RjFicha fichaId;

"Carpeta.java" 的外键 "SubCarpeta.java"

 @OneToMany(mappedBy = "subCarpeta", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @Fetch(FetchMode.SUBSELECT)
    private Collection<item> itemCollection;

Pivot table 与 SubCarpeta 相关 "Item.java"

@JoinColumn(name = "i_subcarpeta_id", referencedColumnName = "sub_id")
    @ManyToOne
    private SubCarpeta subCarpeta;

@Column(name = "i_version")
    @Version
    private Integer version;

这是在描述 NullPointerException 的来源时跟踪的部分

Caused by: java.lang.NullPointerException
    at org.hibernate.type.IntegerType.next(IntegerType.java:63)
    at org.hibernate.type.IntegerType.next(IntegerType.java:22)
    at org.hibernate.engine.internal.Versioning.increment(Versioning.java:92)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:383)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:279)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1300)
    at org.jboss.as.jpa.container.AbstractEntityManager.flush(AbstractEntityManager.java:459)
    ... 141 more

尝试原始 int 而不是包装 class。

@Column(name = "i_version")
@Version
private int version;

Integer 的默认值为 null,int 为 0。

根据 IntegerType API Java 文档,

@Override
    public Integer next(Integer current, SharedSessionContractImplementor session) {
        return current + 1;
    }

如果你保留整数 class null+1 抛出 nullpointerexception

解决方法是将数据库中的table字段设置为NOT NULL和DEFAULT 0。

ALTER TABLE table_name CHANGE COLUMN i_version i_version INT(11) NOT NULL DEFAULT 0;

这是因为如果该字段为 NULL,合并的结果实体会将版本字段获取为 NULL,稍后将抛出 NullPointerException。

这是用于更新实体的代码:

T toReturn = (T)this.em.merge(entity);
this.em.flush();
this.em.refresh(toReturn);
return toReturn;