Spring Jpa Delete Operation Doesn't Work After Fetching Specific List

Viewed 92

These are my entities;

@Entity
 public class IpAddress{

    @Id
    @Column(nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ")
    @Getter
    private Long id;

     @ManyToOne(fetch = FetchType.LAZY)
     private final Application application;

     .....
 }

@Entity
public class Application{

@Column(nullable = false, updatable = false)
private final String applicationId;

@OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
private List<IpAddress> ipAddresses = new ArrayList<>();
}

@Entity
public class MerchantApplication {

    @Id
    @Column(nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ")
    @Getter
    private Long id;
    @OneToOne
    private final Merchant merchant;

    @OneToOne(cascade = CascadeType.ALL)
    private final Application application;

    @ManyToOne(fetch = FetchType.LAZY)
    private final User user;
}

this is the service method that I try to delete:

@Transactional
    public void deleteIpAddressForMerchant(Long merchantId,Long ipAddressId) {

        Merchant merchant = merchantRepository.getMerchant(merchantId);

        MerchantApplication merchantApplication = merchant.getMerchantApplication();

        if (Objects.isNull(merchantApplication))
            throw new ApplicationNotFoundException();

        if (merchantApplication.getApplication().getIpAddresses().size() == 1) {
            throw new IpAddressCannotBeDeleted();
        }

        IpAddress ipAddress = ipAddressRepository.getByIdAndApplication(ipAddressId, merchantApplication.getApplication());
        ipAddressRepository.delete(ipAddress);
    }

it works fine when i remove this block in service method;

if (merchantApplication.getApplication().getIpAddresses().size() == 1) {
            throw new IpAddressCannotBeDeleted();
        }

But this way, it's not work.Can you help me , what is the problem ?

2 Answers

If you fetch an entity field which has orphanRemoval = true property in a @Transactional method, it will save this field with your changes on it when the method returns.

In your case, you fetch

merchantApplication.getApplication().getIpAddresses()

But you didn't any change on it, then the fetched list was saved as it is.

You can remove the element in the fetched list what you want to delete.

you programmatically throw an exception in the following code:

 if (merchantApplication.getApplication().getIpAddresses().size() == 1) 
 {
     throw new IpAddressCannotBeDeleted();
 }

by default transactions are rolled back if a runtime exception happens inside the method that is not handled (try...catch). Does your IpAddressCannotBeDeleted class extend RuntimeException? If so, try adding the following attribute to your @Transactional annotation:

 @Transactional(noRollbackFor={IpAddressCannotBeDeleted.class, ApplicationNotFoundException.class})

The `noRollbackFor´ attribute prevents Spring from rolling back the transaction if exceptions of those two types are being thrown in your method implementation.

Related