BAEL-446: Deleting objects with Hibernate. (#879)
This commit is contained in:
parent
50bc4fb460
commit
d0a6a0ed92
|
@ -40,7 +40,7 @@ public class PersistenceJPAConfigL2Cache {
|
|||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
|
||||
em.setPackagesToScan(getPackagesToScan());
|
||||
|
||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
em.setJpaVendorAdapter(vendorAdapter);
|
||||
|
@ -49,6 +49,10 @@ public class PersistenceJPAConfigL2Cache {
|
|||
return em;
|
||||
}
|
||||
|
||||
protected String[] getPackagesToScan() {
|
||||
return new String[] { "org.baeldung.persistence.model" };
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
|
@ -78,6 +82,7 @@ public class PersistenceJPAConfigL2Cache {
|
|||
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
|
||||
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
|
||||
hibernateProperties.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
|
||||
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
|
||||
return hibernateProperties;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ jdbc.user=sa
|
|||
|
||||
# hibernate.X
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.show_sql=true
|
||||
hibernate.hbm2ddl.auto=create-drop
|
||||
hibernate.cache.use_second_level_cache=true
|
||||
hibernate.cache.use_query_cache=true
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package org.baeldung.persistence.deletion.config;
|
||||
|
||||
import org.baeldung.config.PersistenceJPAConfigL2Cache;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class PersistenceJPAConfigDeletion extends PersistenceJPAConfigL2Cache {
|
||||
|
||||
public PersistenceJPAConfigDeletion() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getPackagesToScan() {
|
||||
return new String[] { "org.baeldung.persistence.deletion.model" };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.baeldung.persistence.deletion.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "BAR")
|
||||
public class Bar {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
List<Baz> bazList = new ArrayList<>();
|
||||
|
||||
public Bar() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Bar(final String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Baz> getBazList() {
|
||||
return bazList;
|
||||
}
|
||||
|
||||
public void setBazList(final List<Baz> bazList) {
|
||||
this.bazList = bazList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Bar [name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.baeldung.persistence.deletion.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "BAZ")
|
||||
public class Baz {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
public Baz() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Baz(final String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Bar [name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package org.baeldung.persistence.deletion.model;
|
||||
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "FOO")
|
||||
@Where(clause = "DELETED = 0")
|
||||
public class Foo {
|
||||
|
||||
public Foo() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Foo(final String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@Column(name = "ID")
|
||||
private long id;
|
||||
|
||||
@Column(name = "NAME")
|
||||
private String name;
|
||||
|
||||
@Column(name = "DELETED")
|
||||
private Integer deleted = 0;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "BAR_ID")
|
||||
private Bar bar;
|
||||
|
||||
public Bar getBar() {
|
||||
return bar;
|
||||
}
|
||||
|
||||
public void setBar(final Bar bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDeleted() {
|
||||
this.deleted = 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package org.baeldung.persistence.service;
|
||||
|
||||
import org.baeldung.persistence.deletion.config.PersistenceJPAConfigDeletion;
|
||||
import org.baeldung.persistence.deletion.model.Bar;
|
||||
import org.baeldung.persistence.deletion.model.Baz;
|
||||
import org.baeldung.persistence.deletion.model.Foo;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { PersistenceJPAConfigDeletion.class }, loader = AnnotationConfigContextLoader.class)
|
||||
public class DeletionIntegrationTest {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
@Autowired
|
||||
private PlatformTransactionManager platformTransactionManager;
|
||||
|
||||
@Before
|
||||
public final void before() {
|
||||
entityManager.getEntityManagerFactory().getCache().evictAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsRemoved_thenItIsNotInDB() {
|
||||
Foo foo = new Foo("foo");
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
foo = entityManager.find(Foo.class, foo.getId());
|
||||
assertThat(foo, notNullValue());
|
||||
|
||||
entityManager.remove(foo);
|
||||
flushAndClear();
|
||||
|
||||
assertThat(entityManager.find(Foo.class, foo.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsRemovedAndReferencedByAnotherEntity_thenItIsNotRemoved() {
|
||||
Bar bar = new Bar("bar");
|
||||
Foo foo = new Foo("foo");
|
||||
foo.setBar(bar);
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
foo = entityManager.find(Foo.class, foo.getId());
|
||||
bar = entityManager.find(Bar.class, bar.getId());
|
||||
entityManager.remove(bar);
|
||||
flushAndClear();
|
||||
|
||||
bar = entityManager.find(Bar.class, bar.getId());
|
||||
assertThat(bar, notNullValue());
|
||||
|
||||
foo = entityManager.find(Foo.class, foo.getId());
|
||||
foo.setBar(null);
|
||||
entityManager.remove(bar);
|
||||
flushAndClear();
|
||||
|
||||
assertThat(entityManager.find(Bar.class, bar.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsRemoved_thenRemovalIsCascaded() {
|
||||
Bar bar = new Bar("bar");
|
||||
Foo foo = new Foo("foo");
|
||||
foo.setBar(bar);
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
foo = entityManager.find(Foo.class, foo.getId());
|
||||
entityManager.remove(foo);
|
||||
flushAndClear();
|
||||
|
||||
assertThat(entityManager.find(Foo.class, foo.getId()), nullValue());
|
||||
assertThat(entityManager.find(Bar.class, bar.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsDisassociated_thenOrphanRemovalIsApplied() {
|
||||
Bar bar = new Bar("bar");
|
||||
Baz baz = new Baz("baz");
|
||||
bar.getBazList().add(baz);
|
||||
entityManager.persist(bar);
|
||||
flushAndClear();
|
||||
|
||||
bar = entityManager.find(Bar.class, bar.getId());
|
||||
baz = bar.getBazList().get(0);
|
||||
bar.getBazList().remove(baz);
|
||||
flushAndClear();
|
||||
|
||||
assertThat(entityManager.find(Baz.class, baz.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsDeletedWithJpaBulkDeleteStatement_thenItIsNotInDB() {
|
||||
Foo foo = new Foo("foo");
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
entityManager.createQuery("delete from Foo where id = :id")
|
||||
.setParameter("id", foo.getId())
|
||||
.executeUpdate();
|
||||
|
||||
assertThat(entityManager.find(Foo.class, foo.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsDeletedWithNativeQuery_thenItIsNotInDB() {
|
||||
Foo foo = new Foo("foo");
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
entityManager.createNativeQuery("delete from FOO where ID = :id")
|
||||
.setParameter("id", foo.getId())
|
||||
.executeUpdate();
|
||||
|
||||
assertThat(entityManager.find(Foo.class, foo.getId()), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public final void givenEntityIsSoftDeleted_thenItIsNotReturnedFromQueries() {
|
||||
Foo foo = new Foo("foo");
|
||||
entityManager.persist(foo);
|
||||
flushAndClear();
|
||||
|
||||
foo = entityManager.find(Foo.class, foo.getId());
|
||||
foo.setDeleted();
|
||||
flushAndClear();
|
||||
|
||||
assertThat(entityManager.find(Foo.class, foo.getId()), nullValue());
|
||||
}
|
||||
|
||||
private void flushAndClear() {
|
||||
entityManager.flush();
|
||||
entityManager.clear();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue