【问题标题】:TransientObjectException in hibernate休眠中的 TransientObjectException
【发布时间】:2025-11-24 22:10:02
【问题描述】:

发送 POST 后

curl localhost:8888/bills/addbill -H "Content-Type: application/json" -X POST -d '{"number":"111A111", "customer":"Customer Customer Rrrr", "phone" :"1 800 5551212", "manager":"经理经理经理", "date":"2012-09-17", "curId":{"id":"1"}, "payments":[{" id":"1", "name":"pomyit stekla","price":"1000.0"}]}'

我明白了:

{"timestamp":1503954247880,"status":500,"error":"内部服务器错误","exception":"org.springframework.dao.InvalidDataAccessApiUsageException","message":"org.springframework.web .util.NestedServletException: 请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: 对象引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例:ru.test.practice.model.Payment;嵌套异常是 java.lang.IllegalStateException: org.hibernate.TransientObjectException: 对象引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例:ru.test.practice.model.Payment","path":"/bills/addbill" }

我的实体“Bill”中有一个多对多关系,这里是引发错误的字段。

账单实体:

    @ManyToMany
    @JoinTable(name="BILL_PAYMENTS",
        joinColumns=
        @JoinColumn(name="payments_id", referencedColumnName="id"),
        inverseJoinColumns=
        @JoinColumn(name="bills_id", referencedColumnName="id")
)
private List<Payment> payments = new ArrayList<>(0);

支付实体:

@ManyToMany(mappedBy = "payments", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
private List<Bill> bills = new ArrayList<>(0);

这是我的 BillService 文件:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.test.practice.dao.BillDao;
import ru.test.practice.model.Bill;
import ru.test.practice.service.BillService;
import ru.test.practice.view.BillView;
import ru.test.practice.model.Payment;
import ru.test.practice.view.PaymentsView;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public class BillServiceImpl implements BillService {

    private final Logger log = LoggerFactory.getLogger(BillServiceImpl.class);

    private final BillDao dao;

    @Autowired
    public BillServiceImpl(BillDao dao) {
        this.dao = dao;
    }


    public List<Payment> convertToPayment(List<PaymentsView> paymentsView){
        List<Payment> payments = new ArrayList<>();
        for(PaymentsView pv : paymentsView) {
            Payment payment = new Payment(pv.id, pv.name, pv.price);
            payments.add(payment);
        }
        return payments;
    }

    public List<PaymentsView> convertToPaymentView(List<Payment> payments){
        List<PaymentsView> paymentsView = new ArrayList<>();
        for(Payment p : payments){
            PaymentsView paymentView = new PaymentsView(p.getId(), p.getName(), p.getPrice());
            paymentsView.add(paymentView);
        }
        return paymentsView;
    }

    @Override
    @Transactional
    public void add(BillView view) {
        List<Payment> payments = convertToPayment(view.payments);
        Bill bill = new Bill(view.id, view.number, view.customer, view.phone, view.manager, view.date, view.curId, payments);
        dao.save(bill);
    }

    @Override
    @Transactional(readOnly = true)
    public List<BillView> bills() {

        List<Bill> all = dao.all();

        Function<Bill, BillView> mapBill = b -> {

            BillView view = new BillView();

            view.id = b.getId();
            view.number = b.getNumber();
            view.customer = b.getCustomer();
            view.phone = b.getPhone();
            view.manager = b.getManager();
            view.date = b.getDate();
            view.curId = b.getCurId();
            view.payments = convertToPaymentView(b.getPayments());

            log.debug(view.toString());

            return view;
        };

        return all.stream()
                .map(mapBill)
                .collect(Collectors.toList());
    }
}

不知道发生了什么,我已经在 * 上检查了类似的问题,但没有帮助。 谢谢c:

【问题讨论】:

    标签: java spring hibernate spring-mvc jpa


    【解决方案1】:

    您正在尝试持久化与瞬态对象相关的对象,您的付款不受管理,因此当您尝试保存账单时,您将收到此异常。

    解决方案 1:您需要保存每笔付款并添加托管对象(从 save 方法返回的对象)。

    解决方案 2:您可以只级联付款,这样当账单持续存在时,付款也会持续存在

    @ManyToMany( cascade = {CascadeType.ALL})
    @JoinTable(name="BILL_PAYMENTS",
        joinColumns=
        @JoinColumn(name="payments_id", referencedColumnName="id"),
        inverseJoinColumns=
        @JoinColumn(name="bills_id", referencedColumnName="id")
    

    【讨论】:

      最近更新 更多