JPA object references an unsaved transient instance - save the transient instance before flushing

11 篇文章 0 订阅

nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : top.lingkang.jpademo.entity.UserRole.role -> top.lingkang.jpademo.entity.Role; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : top.lingkang.jpademo.entity.UserRole.role -> top.lingkang.jpademo.entity.Role] with root cause

当你用jpa或者hibernate进行save时,报以上错误说明你对关联对象进行了修改或者这个管理对象不存在于表中。
例如下面的

/**
 * @author lingkang
 * Created by 2022/7/13
 */
@Data
@Entity
@Table(name = "j_user_role")
public class UserRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//主键递增策略
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "role")
    private Role role;

    @Column
    private String remark;
}

你想直接save一个对象:

    @Transactional
    @GetMapping("add")
    public Object add(){
        UserRole userRole=new UserRole();
        Role role=new Role();
        role.setRole("user");// 随意搞个角色
        role.setDescription("普通用户");
        userRole.setRole(role);
        userRoleRepository.save(userRole);
        return userRole;
    }

就会报以上错误,因为关联关系的值在数据库中不能为空,这里的role角色表少了user这角色导致的。你应该先新增一个角色,否则关联关系不成立。hibernate是一个强关联的ORM,于是改成下面这样就成功了:

    @Transactional
    @GetMapping("add")
    public Object add(){
        UserRole userRole=new UserRole();
        Role role=new Role();
        role.setRole("user");// 随意搞个角色
        role.setDescription("普通用户");
        roleRepository.save(role);// 先保存
        userRole.setRole(role);
        userRoleRepository.save(userRole);
        return userRole;
    }

使用hibernate的关联关系时,尤其要注意关联的对象一定要存在于数据库。

当关联对象不存在,你自己new一个时,他会将你的new的对象持久化

    @Transactional
    @GetMapping("add2")
    public Object add2(){
        List<UserRole> all = userRoleRepository.findAll();
        for (UserRole role:all){
            if (role.getUser()==null){// 关联对象不存在时,他会将你的new的对象持久化
                User user=new User();
                user.setUsername("999999999999999999999999");
                role.setUser(user);
                userRoleRepository.save(role);
            }
        }
        return all;
    }

查看用户表你会发现多了个数据
在这里插入图片描述
所以理清多对多关系比较重要,现在的数据库设计一般都是非强关联的,甚至连个外键都没有。一用hibernate深似海,从此强行联系在一起。

hibernate性能比不上mybatis,多一步查询关联关系(可能会全表扫描),特别是数据极多的时候(一百万以上),性能成吨下降。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌康ACG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值