插入Json值时出现Spring JPA异常(使用hibernate-types-52)



我使用Vlad Mihalcea的hibernate-types-52Spring JPA将POJO作为Json值插入到我的Postgresql数据库中。

我的实体是这样定义的:

@Entity
@Table(name = "hoshin_kanri")
@TypeDef(
name = "jsonb",
typeClass = JsonBinaryType.class
)
public class HKEntity {
@Id
@Column(name = "id_ai", columnDefinition = "bigint")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id_ai;
@Column(name = "id_hk", columnDefinition = "bigint")
private Integer id_hk;
@Type(type = "jsonb")
@Column(name = "hk_data", columnDefinition = "jsonb")
private HKData hk_data;
public HKEntity(Integer id_hk, HKData hk_data) {
this.id_hk = id_hk;
this.hk_data = hk_data;
}

这就是POJO:

public class HKData {
private String name;
private Year targetYear;
private String description;
public HKData(String name, Year targetYear, String description) {
this.name = name;
this.targetYear = targetYear;
this.description = description;
}

我定义了一个Repository接口来将对象查询到数据库中:

public interface HKRepository extends CrudRepository<HKEntity, Integer> {
@Query(value = "INSERT INTO 'hk_data' VALUES :Entity", nativeQuery = true)
void test_json(@Param("Entity") HKEntity e);
}

以及测试服务,看看它是否正常工作:

@Service
public class HKService {
@Autowired
HKRepository hk_repository;
public String json_test() {
HKData d = new HKData("Prova", Year.now(), "Descrizione");
HKEntity e = new HKEntity(1,d);
hk_repository.test_json(e);
return "Value created";
}
}

然而,我一直得到以下异常:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.ehk.rest.entity.HKEntity

我已经尝试了许多针对这个错误的修复方法,但我无法理解错误本身的性质。这种方法有什么问题?除了解决这个问题的技巧外,我还想了解为什么会出现这个错误。

该错误意味着HKEntity实体的一个实例是从当前Hibernate会话中的某个地方引用的,并且您既没有显式地持久化该实例,也没有指示Hibernate随意地持久化它。很难说到底发生了什么,但您的代码中存在一些问题,可能会混淆SpringDataJPA框架或Hibernate本身。

首先,Spring的CrudRepository接口已经有了save()方法,所以您可以使用它来代替test_json()方法。

我也认为插入带有本机查询的Hibernate实体没有任何理由,而且我甚至认为这不是一个有效的查询。test_json()方法尝试以本机方式将HKEntity实体插入到hk_data表中,但根据映射,HKEntity实体应保存到hoshin_kanri表中。

因此,我将更改您的服务代码如下:

public String json_test() {
HKData d = new HKData("Prova", Year.now(), "Descrizione");
HKEntity e = new HKEntity(1,d);
hk_repository.save(e);
return "Value created";
}

最新更新