Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to persist initial data with JpaRepository
    primarykey
    data
    text
    <p>In order to initially fill the database with data, I created entity instances and wrote a service class that should save them in the database.</p> <p>In a very simplified way, my model consists of three classes A, B and C. The instances of the classes A and B both reference (the same) instances of C (annotated with <code>@ManyToOne</code>):</p> <pre><code>a1 -&gt; c1 a2 -&gt; c2 a3 -&gt; c1 b1 -&gt; c1 b2 -&gt; c2 </code></pre> <p>For A and B I use <code>JpaRepositories</code> for persistence.</p> <p>Then I try to save the instances I created programmatically:</p> <pre><code>@Transactional public void save(A a1, A a2, A a3, B b1, B b2) { aRepo.save(a1); aRepo.save(a2); aRepo.save(a3); bRepo.save(b1); bRepo.save(b2); } </code></pre> <p>I get an exception ("detached entity passed to persist: C") in the third line, because the instance c1 got saved already in the first line. </p> <p>How can I avoid that? I thought that marking my save method in my service with <code>@Transactional</code> would be sufficient already, but obviously it's not.</p> <p>Of course I could just write </p> <pre><code>aRepo.save(Arrays.asList(a1, a2, a3)); bRepo.save(Arrays.asList(b1, b2)); </code></pre> <p>but that only shifts my problem as the exception then occurs in the second line when the b1 that references the already saved c1 should get saved.</p> <p>How can I save the data structures I created in one method without getting that exception?</p> <p>Here's the rest of the code:</p> <pre><code>@Entity public class A { @Id @GeneratedValue @Access(AccessType.FIELD) private Long id; @ManyToOne(cascade = CascadeType.ALL) @Access(AccessType.FIELD) private C c; public A(C c) { this.c = c; } public C getC() { return c; } } </code></pre> <p>Class B looks exactly the same, class C only contains the ID parameter.</p> <p>The instances are created within a test case:</p> <pre><code>public class DBTest extends AbstractH2TestCase { @Test public void testDataStorage() { final AbstractApplicationContext context = new AnnotationConfigApplicationContext(DBTest.class); try { final PersistService persistService = context.getBean(PersistService.class); C c1 = new C(); C c2 = new C(); A a1 = new A(c1); A a2 = new A(c2); A a3 = new A(c1); B b1 = new B(c1); B b2 = new B(c2); persistService.save(b1, b2, a1, a2, a3); } finally { context.close(); } } } </code></pre> <p>The superclass for the test I found somewhere on the web and modified it a bit:</p> <pre><code>@Configuration @ComponentScan(basePackageClasses = A.class) @EnableJpaRepositories public class AbstractH2TestCase { public AbstractH2TestCase() { super(); } @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(H2).build(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { final LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean(); lef.setDataSource(dataSource); lef.setJpaVendorAdapter(jpaVendorAdapter); final String thisPackageAndSubpackages = this.getClass().getPackage().getName(); lef.setPackagesToScan(thisPackageAndSubpackages); return lef; } @Bean public JpaVendorAdapter jpaVendorAdapter() { final HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); hibernateJpaVendorAdapter.setShowSql(false); hibernateJpaVendorAdapter.setGenerateDdl(true); hibernateJpaVendorAdapter.setDatabase(Database.H2); return hibernateJpaVendorAdapter; } @Bean public PlatformTransactionManager transactionManager() { return new JpaTransactionManager(); } } </code></pre> <p>If you want a running version of the code - I checked it in here:</p> <p><a href="https://github.com/BernhardBln/stackexchange" rel="nofollow">https://github.com/BernhardBln/stackexchange</a></p> <p>It's a maven project.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload