I have a ManyToMany relation between my Walletand Voucherclass.
public class Wallet {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// The total amount in the voucher
private float amount = 0;
//the list of voucher in the wallet
@OneToMany(mappedBy = "wallet", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserVoucher> userVouchers = new HashSet<>();
@OneToOne(mappedBy = "wallet")
private AppUser appUser;
}
Voucher
public class Voucher {
@Id
private String code;
private Date generationDate;
private Date endDate;
private float amount;
private float minForBuy; // minimun needed to use the voucher during transaction
private int nb = 1; // for example, for a voucher of 2 euros, with nb = 4, the amount will be 2/4, so 0,5€
//the list of voucher in the wallet
@OneToMany(mappedBy = "voucher")
Set<UserVoucher> userVouchers = new HashSet<>();
/**
*
* @param code
* @param endDate
* @param amount
* @param nb
*/
public Voucher(String code, Date endDate, float amount, float minForBuy, int nb) {
super();
this.code = code;
this.generationDate = new Date();
this.endDate = endDate;
this.amount = amount;
this.minForBuy = minForBuy;
this.nb = nb;
}
}
And my join table uservoucher
public class UserVoucher {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private int voucherNb;
private Date activateDate;
private Date useDate;
@ManyToOne
@JoinColumn(name = "wallet_id")
@MapsId("walletId")
Wallet wallet;
@ManyToOne
@JoinColumn(name = "vouher_id")
@MapsId("voucherId")
Voucher voucher;
/**
* required param
* @param id
* @param voucherNb
* @param activateDate
*/
public UserVoucher(int voucherNb, Voucher voucher, Wallet wallet) {
super();
this.voucherNb = voucherNb;
this.activateDate = new Date();
this.voucher = voucher;
this.wallet = wallet;
}
}
In my test, i created a voucher, a wallet, then i add the voucher in uservucher list:
public Wallet addVoucher(String voucherCode, Wallet wallet) {
logger.info("Add voucher with code {}", voucherCode);
// first we check if the voucher exist and still valid
if(!voucherService.isVoucherExistAndValid(voucherCode)) {
throw new GaraAppUserException("The voucher doesn't exist or is expired", HttpStatus.NOT_FOUND);
}
//We get the voucher
Optional<Voucher> voucherOpt = voucherRepo.findById(voucherCode);
List<UserVoucher> userVoucherList = new ArrayList<>();
//If the voucher exist
if(voucherOpt.isPresent()) {
Voucher voucher = voucherOpt.get();
//We create the user voucher
float amount = 0;
for(int i=1; i <= voucher.getNb(); i++) {
UserVoucher userVoucher = new UserVoucher(i, voucher, wallet);
userVoucherList.add(userVoucher);
amount += voucher.getAmount();
}
// save the list in the list of user voucher
if(!userVoucherList.isEmpty()) {
this.userVoucherService.saveAll(userVoucherList);
}
logger.info("The old wallet amount is {} ", voucher.getAmount());
float totalAmount = wallet.getAmount() + amount;
wallet.setAmount(totalAmount);
//The amount changed
logger.info("The new wallet amount is {} ", totalAmount);
wallet = this.walletRepo.save(wallet);
}
return wallet;
}
I don't know why during the saveAll i got the error:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.gara.mappuser.model.wallet.Wallet; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.gara.mappuser.model.wallet.Wallet
All solutions i tried doesn't work for me. I saw the same question with 21 answers but none work for me. I tried cascade merged by still same issue. How could i correct it please ?