Wpis z mikrobloga

Mircy dlaczego taki kod:

Session session = transactionManager.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
Item item = new Item();
session.persist(item);
item.setName("nowyItem");
Bid bid = new Bid();
bid.setAmount(100);
item.getBids().add(bid);
transaction.commit();

Zapisuje mi sam item bez bid'a , mimo że zatwierdzam transakcję dopiero na końcu? jeśli przerzucę session.persist nad transaction.commit, to oba przedmioty są zapisywane ( ͡° ʖ̯ ͡°) Coś nie tak z dirty checking?
@interface może Ty coś wiesz ( ͡° ͜ʖ ͡°)
#hibernate #jpa #java #programowanie #naukaprogramowania
  • 19
  • Odpowiedz
@Vaping_cool: mam to dodane, dokladnie tak

@Entity
public class Bid {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Item item;

@Entity
@ToString
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@OneToMany(mappedBy = "item", cascade = CascadeType.PERSIST)
private Set bids = new HashSet<>();

public Set getBids() {
return bids;
}

public void setBids(Set bids) {
this.bids = bids;
}
  • Odpowiedz
@Godziu73: CascadeType.PERSIST jest powiązana z metodą persist(), tak jak CascadeType.MERGE z metodą merge() itp. Metoda persist sprawia, że Item przechodzi ze stanu new w managed (powiązanie z kontekstem utrwalania), natomiast Bid jest zwykłym obiektem i takim pozostaje, nie ma tutaj znaczenia, że ten obiekt tworzysz w ramach transakcji.
Jeśli persist() przeniesiesz przed sam commit, to operacje persist() jest kaskadowo przenoszona także na wszystkie Bidy zgodnie z cascade type, więc one też
  • Odpowiedz
@Godziu73: CascadeType.PERSIST z tego co ja wiem odpowiada za to, że gdy dasz właśnie session.persist() przed commitem to zasavuje także Bidy, bez cascade nie powinien, czyli to niewiele zmienia w twoim przypadku. Spróbuj dodać bid.setItem(twojItem).
  • Odpowiedz
@Eoghan: ale jeśli bid dodaję do kolekcji zarządzanego obiektu ( item.getBids().add(bid);) to czy od tej pory bid nie staje się też obiektem zarządzanym? Chodzi mi o taką sytuację jak wkleiłem screen powyżej
@Porana123: spróbowałem, nie pomogło ( ͡° ʖ̯ ͡°)
  • Odpowiedz
@Godziu73: nie, jeśli zarówno Bid jak i Item byłyby managed, to wtedy możesz się nimi bawić w ramach transakcji tworząc relacje, jeśli Bid jest new, a Item jest managed, to nic tutaj się nie stanie (Bid nie zostanie zapisany). Jeszcze raz - CascadeType.PERSIST nie oznacza "jeśli dodałem cokolwiek do kolekcji to to zapisz", tylko "jeśli na obiekcie wywołałem metodę persist() to wywołaj ją także na każdym elemencie kolekcji". Rzuć okiem na
  • Odpowiedz
@Godziu73: opcji jest kilka i może to np. przy jakichś typowo hibernatowych (a nie jpa) adnotacjach działa nieco inaczej. Pierwsza rzecz, to pobierz kody źródłowe do książki i przetestuj, czy działa. Jaka to książka, z którego roku i której wersji hibernate?
  • Odpowiedz
@Eoghan: Java Persistance with Hibernate Second Edition, z 2015 r, do Hibernate 5

To wytłumacz mi czy gdzieś robię błąd, powinno to działać tak:
1) Tworzę nowy obiekt Item i wywołuję z nim metodę persist() - od tej pory Item jest w stanie managed
a więc jeśli zmieni się jego stan, to zmiany zostaną zapisane do bazy (dirty checking)
2) tworzę nowy obiekt bid, jest to zwykły obiekt javowy, niezwiązany z
  • Odpowiedz
@Eoghan: wiesz co, to raczej coś powiązane z hibernate, gdy zmieniłem na
@OneToMany(mappedBy = "item", cascade = CascadeType.ALL)
to teraz zapisywane są bidy ( z takim samym kodem jak we wpisie), chyba transaction.commit(); nie działa tak jak sobie to wyobrażam
  • Odpowiedz
@Godziu73: hm w sumie tak sobie czytam specyfikację jpa i szczerze mówiąc to mam wrażenie, że są tam pewne szczegóły, które dają pole do własnej interpretacji i to co pisałem wcześniej nie musi zawsze być prawdą. W sumie to ciekaw jestem, czy eclipse link zachowuje się tak samo w tej kwestii i w wolnej chwili się pobawię tutaj różnymi przypadkami i popytam gdzieś na stacku
  • Odpowiedz
@Eoghan: nie wiem czy to ma jakieś znaczenie ale do uzyskania Session używam

import org.springframework.orm.hibernate5.HibernateTransactionManager;

Dzięki za zainteresowanie :)
  • Odpowiedz