下面是寵物店的簡單模型......
寵物班
@Entity
@Table(name = "pet")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public abstract class Pet {
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "birth_date", nullable = false)
private LocalDate birthDate;
@Column(name = "death_date")
private LocalDate deathDate;
@ManyToOne
@JoinColumn(name = "pet_shop_id", nullable = false, referencedColumnName = "id")
@Setter(AccessLevel.NONE)
private PetShop petShop;
public void setPetShop(PetShop petShop) {
setPetShop(petShop, true);
}
public void setPetShop(PetShop petShop, boolean add) {
this.petShop= petShop;
if (petShop!= null && add) {
petShop.addPet(this, false);
}
}
寵物店類
@Entity
@Table(name = "pet_shop")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class PetShop {
@Column(name = "id", nullable = false)
private Long id;
...
@OneToMany(
mappedBy = "petShop",
fetch = FetchType.LAZY,
cascade = {CascadeType.ALL})
private List<Pet> pets= new ArrayList<>();
public void addPet(final Pet pet) {
addPet(pet, true);
}
public void addPet(final Pet pet, boolean set) {
if (pet!= null) {
if (pets.contains(pet)) {
pets.set(pets.indexOf(pet), pet);
} else {
pets.add(pet);
}
if (set) {
pet.setPetShop(this, false);
}
}
}
}
PetShopRepository 介面
public interface PetShopRepository
extends JpaRepository<PetShop, Long> {
@Query(
"SELECT DISTINCT ps FROM PetShop ps"
" JOIN ps.pets p"
" WHERE ps.id = :id AND p.deathDate IS NULL")
@Override
Optional<PetShop> findById(@NonNull Long id);
}
...這里是如何創建一個PetShop有 2 個Pet實體(一個活著,另一個死了)的方法:
final Pet alive = new Pet();
alive.setName("cat");
alive.setCall("meow");
alive.setBirthDate(LocalDate.now());
final Pet dead = new Pet();
dead.setName("cat");
dead.setCall("meow");
dead.setBirthDate(LocalDate.now().minusYears(15L));
dead.setDeathDate(LocalDate.now());
final PetShop petShop = new PetShop();
petShop.getPets().add(alive);
petShop.getPets().add(dead);
petShopRepositiry.save(petShop);
現在我想檢索PetShop并且我假設它只包含活著的寵物:
final PetShop petShop = petShopRepository.findById(shopId)
.orElseThrow(() -> new ShopNotFoundException(shopId));
final int petCount = petShop.getPets().size(); // expected 1, but is 2
根據我的自定義查詢,PetShopRepository我希望petShop.getPets()回傳一個包含 1 個元素的串列,但它實際上回傳一個包含 2 個元素的串列(它還包括死去的寵物)。
Am I missing something? Any hint would be really appreciated :-)
uj5u.com熱心網友回復:
這是因為盡管您有查詢,Jpa 仍保持關系的連貫性。
即:您的查詢回傳至少有一只寵物活著的商店。但是,Jpa 會將整套寵物歸還給商店。你可能會看到 Jpa 發送額外的 sql 查詢(如果你設定show_sql=true)以重新填充回傳商店的寵物集合。
從根本上說,并不是因為你想讓商店里有活的寵物,這些商店才會放掉他們死去的寵物。
要做到這一點,您必須設計寵物集合,以便過濾死去的寵物。Hibernate 提供了這樣的注釋(@Filter和@FilterDef),但顯然 JPA 沒有。
我不認為過濾 at@Postload是個好主意,因為在資料庫中進行任何重繪 之前,您必須將過濾后的死寵物放回集合中。這對我來說看起來很冒險。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/537613.html
