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() {
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||||
em.setDataSource(dataSource());
|
em.setDataSource(dataSource());
|
||||||
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
|
em.setPackagesToScan(getPackagesToScan());
|
||||||
|
|
||||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||||
em.setJpaVendorAdapter(vendorAdapter);
|
em.setJpaVendorAdapter(vendorAdapter);
|
||||||
|
@ -49,6 +49,10 @@ public class PersistenceJPAConfigL2Cache {
|
||||||
return em;
|
return em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String[] getPackagesToScan() {
|
||||||
|
return new String[] { "org.baeldung.persistence.model" };
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DataSource dataSource() {
|
public DataSource dataSource() {
|
||||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
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_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.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.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
|
||||||
|
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
|
||||||
return hibernateProperties;
|
return hibernateProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ jdbc.user=sa
|
||||||
|
|
||||||
# hibernate.X
|
# hibernate.X
|
||||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||||
hibernate.show_sql=false
|
hibernate.show_sql=true
|
||||||
hibernate.hbm2ddl.auto=create-drop
|
hibernate.hbm2ddl.auto=create-drop
|
||||||
hibernate.cache.use_second_level_cache=true
|
hibernate.cache.use_second_level_cache=true
|
||||||
hibernate.cache.use_query_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