【发布时间】:2019-12-08 09:03:24
【问题描述】:
我正在为在线电影票务服务开发 Java Spring Web 应用程序。
用户拥有指定数量的积分,并且可以使用这些积分来支付部分门票。如果用户决定取消交易,他的积分将得到补偿。这些点移动称为 PointTransactions。
事务存储在事务表中,而 PointTransactions 存储在带有对父事务的引用的 pointTransactions 表中。
我在持久化在同一方法上引用新事务实体的 PointTransaction 实体时遇到问题。
这是我目前使用的代码:
@Override
@Transactional
public TransactionDTO confirmCheckout(...) {
/**Validations removed and parameters simplified to improve readability**/
Transaction transaction = transactionDao.create(...);
pointsTransactionDao.create(transaction, ...);
return new TransactionDTO(transaction);
}
DAO 函数已经过适当的测试并且可以独立工作,但是在运行上述代码时,我收到以下异常。
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
at ar.edu.itba.paw2018b.persistence.PointTransactionsHibernateDaoImpl.create(PointTransactionsHibernateDaoImpl.java:32)
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "pointtransactions" violates foreign key constraint "pointtransaction_transaction_transid_fk"
Detail: Key (transaction)=(23) is not present in table "transactions".
在运行时查看代码时,我可以确认 ID = 23 的事务是在 confirmCheckout() 方法中创建的事务。 似乎违反了约束,因为在 PointTransaction 记录之前未将 Transaction 记录提交到 DB。
此错误开始于我将我的 EntityManagers 的 PersistenceContext 从默认更改为 ExtendedType,更改是由于我需要延迟初始化我的大部分引用而推动的。我相信这个问题与此密切相关,但是我对 Hibernate 的了解还不够,无法推断出解决该问题的最佳方法。
下面是我的 Daos 和 Models 的代码。
感谢您的宝贵时间。
@Repository
public class TransactionHibernateDaoImpl implements TransactionDao {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
@Override
public Transaction create(User userId, Screening screeningId, String seat, String food, double price, boolean paid, Timestamp date, String confirmationCode, int status) {
final Transaction transaction = new Transaction(userId,screeningId,seat,food,price,date,paid,confirmationCode, status);
em.persist(transaction);
return transaction;
}
public void setEm(EntityManager em) {
this.em = em;
}
/** Unrelated Methods **/
}
.
@Repository
public class PointTransactionsHibernateDaoImpl implements PointTransactionsDao {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
@Override
public PointTransactions create(User userid, int conversion, Transaction transaction, int price, int reason, Timestamp date)
{
final PointTransactions ptransaction = new PointTransactions(userid,conversion,transaction,price, reason, date);
em.persist(ptransaction);
return ptransaction;
}
public void setEm(EntityManager em) {
this.em=em;
}
/** Unrelated Methods **/
}
.
@Entity
@Table(name = "pointtransactions")
public class PointTransactions {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@SequenceGenerator(sequenceName = "transactions_transid_seq", name = "transactions_transid_seq", allocationSize = 1)
@Column(name = "pointtransid", nullable = false)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userid")
private User userid;
@Column
private int conversion;
@Column
private Timestamp date;
@Column
private int price;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "transaction")
private Transaction transaction;
@Column(nullable = false)
private int reason;
public PointTransactions(){}
public PointTransactions(User userId, int conversion, Transaction transaction, int price, int reason, Timestamp date){
this.userid = userId;
this.conversion = conversion;
this.transaction = transaction;
this.price = price;
this.reason = reason;
this.date = date;
}
/** Getters and Setters **/
}
.
@Entity
@Table(name = "transactions")
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@SequenceGenerator(sequenceName = "transactions_transid_seq", name = "transactions_transid_seq", allocationSize = 1)
@Column(name = "transid", nullable = false)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userid")
private User userid;
@Column(name = "transactiondate",nullable = false)
private Timestamp date;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "screeningid")
private Screening screeningid;
@Column(nullable = false)
private String seat;
@Column(name = "fooddetails", length = 1024)
private String food;
@Column(nullable = false)
private double price;
@Column(nullable = false)
private boolean paid = false;
@Column
private String confirmationCode;
@Column
private int status;
public Transaction(){}
public Transaction( User userId, Screening screeningId, String seat, String food, double price, Timestamp date, boolean paid, String confirmationCode, int status){
this.userid = userId;
this.date = date;
this.screeningid = screeningId;
this.seat = seat;
this.food=food;
this.price = price;
this.paid = paid;
this.confirmationCode = confirmationCode;
this.status = status;
}
/** Getters and Setters **/
}
【问题讨论】:
标签: java spring hibernate constraints