Please, see method testCollections(). Two objects are created and inserted to collection. Then one of them is removed from collection. Everything works perfect, single row is added in DB. But if we execute any sql query before removing object from collection, hibernated assigns PK for new objects and they are stored in DB both, regardless that in collection is single object... Any idea how to explain it to hibernate?
@Entity
@Table(name = "animalowner")
public class Owner {
@Id
@Column
private Long id;
@Column(name = "owner_name")
private String name;
@OneToMany(fetch = FetchType.EAGER, targetEntity = Animal.class, cascade = { CascadeType.ALL }, orphanRemoval = true)
@JoinColumn(name = "owner_fk")
private Set<Animal> animals;
......
@Entity
@Table(name = "animals")
public class Animal {
public Animal(String name, Owner owner) {
this.name = name;
this.owner = owner;
}
public Animal() {
}
@Id
@GeneratedValue(generator = "animal_generator")
@SequenceGenerator(name = "animal_generator", sequenceName = "animal_sequence")
private Long id;
@Column(name = "cat_name")
private String name;
@ManyToOne(targetEntity = Owner.class, fetch = FetchType.EAGER)
@JoinColumn(name = "owner_fk")
private Owner owner;
.........
@Component
public class SomeService {
.....
@Override
@Transactional
public void testCollections(){
Owner owner = repository.loadOwnerById(1L);
Set<Animal> animals = owner.getAnimals();
Animal animal1 = new Animal("animal1", owner);
Animal animal2 = new Animal("animal2", owner);
animals.add(animal1);
animals.add(animal2);
//IF any SQL called here, hibernate assigns primary keys for animal1 and animal2,
//and 2 objects are saved to database.
animals.remove(animal1);
}
.....
That's because Owner is attached to the current running PersistenceContext:
Owner owner = repository.loadOwnerById(1L);
and the moment you add any Animal to the animals collection:
@OneToMany(fetch = FetchType.EAGER, targetEntity = Animal.class, cascade = { CascadeType.ALL }, orphanRemoval = true)
@JoinColumn(name = "owner_fk")
private Set<Animal> animals;
Upon executing a query the flush mechanism kicks in. Hibernate dirty checking mechanism detects the owner has changes and it synchronizes any change with the database.
The transitive persistence mechanism is going to save all new Children entities:
If a transient or detached child becomes referenced by a persistent parent, it is passed to saveOrUpdate()
That's why the Animals get saved without any explicit flush.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments