问题已经有很长时间了,但我有类似的问题,希望我的回答能帮助到别人。
假设我们有这个 JPA 实体:
@Entity
@Table(name = "card_transactions")
public class CardTransactionsEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "card_trans_seq")
@SequenceGenerator(name = "card_trans_seq", sequenceName = "card_trans_seq")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "ofd_id", referencedColumnName = "ofd_id"),
@JoinColumn(name = "receipt_id", referencedColumnName = "receipt_id")})
private ReceiptsEntity receipt;
@Column
@Enumerated(EnumType.STRING)
private CardTransactionStatus requestStatus;
...
}
@Entity
@Table(name = "receipts")
public class ReceiptsEntity {
@EmbeddedId
private OfdReceiptId id;
...
}
@Embeddable
public class OfdReceiptId implements Serializable {
@Column(name = "ofd_id")
@Enumerated(EnumType.STRING)
private OfdId ofdId;
@Column(name = "receipt_id")
private String receiptId;
...
}
并且我们希望选择 CardTransactionsEntity 和获取的 ReceiptsEntity 用于悲观更新 CardTransactionsEntity。这可以使用 Hibernate 和 Spring Data JPA 存储库来完成
public interface CardTransactionRepository extends JpaRepository<CardTransactionsEntity, Long> {
@Query("select ct from CardTransactionsEntity ct left join fetch ct.receipt r where ct.requestStatus = :requestStatus")
@Lock(value = LockModeType.PESSIMISTIC_WRITE)
@QueryHints(value = {
@QueryHint(name = "javax.persistence.lock.timeout", value = "-2"), // LockOptions.SKIP_LOCKED
@QueryHint(name = "org.hibernate.lockMode.r", value = "NONE") // "r" is alias for ct.receipt and will excluded from PESSIMISTIC_WRITE
})
List<CardTransactionsEntity> loadCardTransactions(@Param("requestStatus") CardTransactionStatus requestStatus, Pageable pageable);
}
这个存储库方法会像这样执行查询
SELECT ct.*, r.* from card_transactions ct LEFT OUTER JOIN receipts r ON ct.ofd_id = r.ofd_id and ct.receipt_id = r.receipt_id WHERE ct.request_status=? LIMIT ? FOR UPDATE OF ct SKIP LOCKED