0

I have entity Ad:

@Entity
@NamedQueries({
    @NamedQuery(name =  "getAllAds",
            query = "from Ad"),
    @NamedQuery(name =  "deleteById",
    query = "delete from Ad where id = :id")
})
@FieldMatch(first = "initLanguage",second = "resultLanguage", message = "Languages must be different")
@Table(name = "AD_TEST")
public class Ad  implements Serializable{

    /**
     * Version of this class in production 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "standard", initialValue = 1)
    @GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
    @Column(name = "AD_ID")
    private long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CLIENT",nullable = false)
    private Client client;

    @NotBlank
    @Column(name = "AD_NAME", nullable = false)
    private String name;

    @NotBlank
    @Column(name = "AD_DESC",nullable = false,length = 1000)
    @Lob
    @Size(min = 0, max = 1000)
    private String description;

    @Column(name = "AD_COUNTRY", nullable = false)
    private String country;

    @Column(name = "AD_CITY", nullable = false)
    private String city;


    @NotNull
    /**
     * Добавить проверку валидности даты
     */
    @DateTimeFormat(iso = ISO.DATE,pattern = "dd.MM.yyyy")
    @Column(name = "AD_END_DATE",nullable = false)
    private LocalDate endDate;

    @NotNull
    @Column(name = "AD_INIT_LANGUAGE",nullable = false)
    @Enumerated(EnumType.STRING)
    private Language initLanguage;

    @NotNull
    @Column(name = "AD_RESULT_LANGUAGE",nullable = false)
    @Enumerated(EnumType.STRING)
    private Language resultLanguage;

    @NotNull
    @Column(name = "AD_TRANSLATE_TYPE",nullable = false)
    @Enumerated(EnumType.STRING)
    private TranslateType translateType;

    @Lob
    @Column(name = "AD_FILE")
    private byte[] file;

    @NotNull
    @Column(name = "AD_COST",nullable = false,precision = 2)
    private double cost;

    @NotNull
    @Column(name = "AD_CURRENCY",nullable = false)
    @Enumerated(EnumType.STRING)
    private Currency currency;

    @Column(name = "AD_CREATING_DATE",nullable = false)
    private LocalDateTime creationDateTime;

    @Column(name = "AD_STATUS",nullable = false)
    @Enumerated(EnumType.STRING)
    private AdStatus status;

    @OnDelete(action = OnDeleteAction.CASCADE)
    @OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "ad")
    @Cascade(CascadeType.ALL)
    private List<ResponsedAd> responsedAds = new ArrayList<>();

    public Ad(){}
    /*Getters and setters,  hashCode and equals*/

Ad is element of collection in Client:

@Entity
@NamedQueries({
    @NamedQuery(name =  "clientByEmail",
                query = "from Client client where client.email = :email")
})
@Table(name = "CLIENT_TEST")
@PrimaryKeyJoinColumn(name= "client_id")
public class Client extends User{

    /**
     * Version of this class in production 
     */
    private static final long serialVersionUID = 1L;

    @OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
    @Cascade(CascadeType.ALL)
    public List<Ad> ads = new ArrayList<>();

    @OneToMany(fetch = FetchType.EAGER,orphanRemoval = true,mappedBy = "client")
    @Cascade(CascadeType.ALL)
    private List<ResponsedAd> responsedAds = new ArrayList<>();

    public Client(){}

Ad.class and Client.class have collection of ResponseAd objects:

@Entity
@Table(name = "RESPONSED_AD_TEST")
@NamedQueries({
    @NamedQuery(name = "responsedAdsByAd",query="from ResponsedAd where ad = :ad")
})
@Component
public class ResponsedAd {

    @Id
    @SequenceGenerator(name = "standard", initialValue = 1)
    @GeneratedValue(generator = "standard", strategy =GenerationType.SEQUENCE)
    private long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "AD",nullable = false)
    private Ad ad;

    @Column(nullable = false)
    private LocalDateTime dateTimeOfResponse;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CLIENT")
    private Client client;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TRANSLATOR",nullable = false)
    private Translator translator;

    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private ResponsedAdStatus status;


    public ResponsedAd(){}

I want that after deleting Ad object, all ResponseAd objects from collection were deleted too.

For this I have:

public void deleteById(long id){
    Ad ad = get(id);
    CopyOnWriteArrayList<ResponsedAd> list = new CopyOnWriteArrayList<>(ad.getResponsedAds());
    list.forEach(rad->{
        Translator translator = rad.getTranslator();
        translator.removeResponsedAd(rad);
        ad.removeResponsedAd(rad);
        Client client = rad.getClient();
        client.removeResponsedAd(rad);
    });
    Client client = ad.getClient();
    client.removeAd(ad);
}

Say me please, how can I do this right? I have very a lot of relationships and when I try do this, I get error

HTTP Status 500 - Request processing failed; nested exception is 
org.springframework.dao.InvalidDataAccessApiUsageException: 
deleted object would be re-saved by cascade (remove deleted object from associations): 
[ua.translate.model.ad.ResponsedAd#102]; nested exception is org.hibernate.ObjectDeletedException: 
deleted object would be re-saved by cascade (remove deleted object from associations): [ua.translate.model.ad.ResponsedAd#102]
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Yuriy
  • 1,370
  • 4
  • 14
  • 30

2 Answers2

0

First of all,

You don't need to use @NotNull if you have nullable = false already declared in @Column(nullable = false).

Second,

What you're trying to do is doing operations in Cascade. Add this cascade = CascadeType.ALL or maybe cascade = CascadeType.REMOVE to your @ManyToOne tags and it should work.

Use this as a reference: JPA @ManyToOne with CascadeType.ALL

Community
  • 1
  • 1
Julian
  • 344
  • 1
  • 11
  • But I have @Cascade(CascadeType.ALL) with every collection. I use Hibernate session for all actions – Yuriy Jul 22 '16 at 17:12
  • And I need deleting all responseAd entities, when I delete their parent(Ad), but not vice versa – Yuriy Jul 22 '16 at 17:19
  • See this [question](http://stackoverflow.com/questions/6915102/deleting-entity-causes-objectdeletedexception-in-hibernate) it seems you're giving too many remove commands. – Julian Jul 22 '16 at 17:37
0

My Client object: Client client = rad.getClient(); have two responsedAd object in collection with the same id, therefore even after deleting this responsedAd object: client.removeResponsedAd(rad); client object has one more. And now main question is why this client have two objects with the same id.

Yuriy
  • 1,370
  • 4
  • 14
  • 30