2016-08-09 5 views
0

У меня есть класс ResponsedAd:Saving элемент коллекции в спящем режиме

@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) 
@Cascade(CascadeType.REMOVE) 
@JoinColumn(name = "AD",nullable = false) 
private Ad ad; 

@Column(nullable = false) 
private LocalDateTime dateTimeOfResponse; 

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "CLIENT",nullable = false) 
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(){} 

Он имеет @ManyToOne отношение к классам: Клиент, Ad, Переводчик

Клиент:

@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(){} 

    public static long getSerialversionuid() { 
     return serialVersionUID; 
    } 
    public List<Ad> getAds() { 
     return ads; 
    } 

    public void setAds(List<Ad> ads) { 
     this.ads = ads; 
    } 

    public void addAd(Ad ad){ 
     ads.add(ad); 
     ad.setClient(this); 
    } 

    public void removeAd(Ad ad){ 
     ads.remove(ad); 
     ad.setClient(null); 
    } 

    public List<ResponsedAd> getResponsedAds() { 
     return responsedAds; 
    } 

    public void addResponsedAd(ResponsedAd responsedAd){ 
     responsedAds.add(responsedAd); 
     responsedAd.setClient(this); 
    } 

    public void removeResponsedAd(ResponsedAd responsedAd){ 
     responsedAds.remove(responsedAd); 
     responsedAd.setClient(null); 
    } 

объявление:

@Entity 
@NamedQueries({ 
    @NamedQuery(name = "getAllAds", 
      query = "from Ad"), 
    @NamedQuery(name = "deleteById", 
    query = "delete from Ad where id = :id") 
}) 
@FieldNotMatch(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; 


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

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

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

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

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

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

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

    @Column(name = "AD_PUBLICATIO_DATE_TIME",nullable = false) 
    private LocalDateTime publicationDateTime; 

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

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

    public Ad(){} 

Это я thod для сохранения ResponsedAd:

@Override 
    public void saveResponsedAd(String email,long adId) throws NonExistedAdException { 
     Ad ad = adDao.get(adId); 
     if(ad == null){ 
      throw new NonExistedAdException(); 
     } 

     ResponsedAd responsedAd = new ResponsedAd(); 

     Translator translator = translatorDao.getTranslatorByEmail(email); 
     Client client = ad.getClient(); 

     translator.addResponsedAd(responsedAd); 
     client.addResponsedAd(responsedAd); 
     ad.addResponsedAd(responsedAd); 

     responsedAd.setStatus(ResponsedAdStatus.SENDED); 
     responsedAd.setDateTimeOfResponse(LocalDateTime.now()); 

     responsedAdDao.save(responsedAd); 

    } 

После сохранения у меня есть соответствующая строка в таблице Responsed_Ad_Test.

, когда я хочу удалить объявление У меня есть ошибка, мой объект-клиент из метода ниже имеет 3 одинаковых ответчика, и у меня есть исключение: удаленный объект будет повторно сохранен cascade (удалить удаленный объект из ассоциаций).

И я не знаю, почему мой клиент повторил объект ResponsedAd, экономя при этом мой клиентский объект имеет объект только 1 ResponsedAd

@Override 
    public void deleteById(long id) throws NonExistedAdException,UnacceptableActionForAcceptedAd{ 
     Ad ad = get(id); 
     if(ad.getStatus().equals(AdStatus.ACCEPTED)){ 
      throw new UnacceptableActionForAcceptedAd(); 
     } 
     List<ResponsedAd> list = new ArrayList<>(ad.getResponsedAds()); 
     list.stream().forEach(rad->{ 
      Translator translator = rad.getTranslator(); 
      Client client = rad.getClient(); 
      translator.removeResponsedAd(rad); 
      ad.removeResponsedAd(rad); 
      client.removeResponsedAd(rad); 
     }); 

     Client client = ad.getClient(); 
     client.removeAd(ad); 
    } 

Я понимаю, что проблема заключается в сохранении объекта ResponsedAd, но я не могу понимаете создание нескольких одинаковых объектов ResponsedAd для клиента. Помогите пожалуйста :)

ответ

0

Проблема заключалась в энергичной инициализации коллекций. Поскольку эта инициализация загружает дублированные объекты. Я изменил FetchType с EAGER на LAZY, и проблема решена)