Spring Data JPA: Fetching data from entity just after save() method
Solution 1
This might be a bit outdated, but I ran into the same issue and found that hibernate 2nd level cache was the issue.
Solution 2
The save() method may or may not write your changes to database immediately. If you want to commit the changes immediately, you will need to use T saveAndFlush(T entity)
method.
Admin
Updated on June 05, 2022Comments
-
Admin almost 2 years
I'm using Spring Data JPA with Hibernate JPA provider in my project. Inside my service I have a method, which saves an entity in database and than using returned object I try to fetch more details about this entity. As a result, details are not fetched. In logs I see only insert statement, without select for details.
Here is my code:
Configuration:
@Configuration @Profile("test") @EnableJpaRepositories(basePackages = {"pl.lodz.uml.sonda.common.repositories"}) @EnableTransactionManagement @PropertySource(value = "classpath:db.test.properties") public class PersistenceConfigTest { @Autowired private Environment env; @Value("classpath:sql/test-initialization.sql") private Resource sqlInitializationScript; @Bean public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); dataSource.setUrl(env.getProperty("jdbc.url")); dataSource.setUsername(env.getProperty("jdbc.username")); dataSource.setPassword(env.getProperty("jdbc.password")); return dataSource; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean(); HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setShowSql(env.getProperty("hibernate.showSQL", Boolean.class)); adapter.setGenerateDdl(env.getProperty("hibernate.hbm2ddl", Boolean.class)); entityManagerFactory.setDataSource(dataSource()); entityManagerFactory.setPackagesToScan("pl.lodz.uml.sonda.common.domains"); entityManagerFactory.setJpaVendorAdapter(adapter); Properties properties = new Properties(); properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); entityManagerFactory.setJpaProperties(properties); return entityManagerFactory; } @Bean(name = "transactionManager") public PlatformTransactionManager platformTransactionManager() { EntityManagerFactory entityManagerFactory = entityManagerFactory().getObject(); return new JpaTransactionManager(entityManagerFactory); } @Bean public DataSourceInitializer dataSourceInitializer() { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScript(sqlInitializationScript); DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource()); initializer.setDatabasePopulator(populator); initializer.setEnabled(env.getProperty("db.initialization", Boolean.class)); return initializer; } @Bean public ProbeService probeService() { return new ProbeServiceImpl(); } }
Service:
@Service @Transactional public class ProbeServiceImpl implements ProbeService { @Autowired private ProbeRepository probeRepository; @Override public Probe saveProbe(Probe probe) { Probe saved = probeRepository.save(probe); saved.getGroup().getName(); return saved; } }
Simple test:
@RunWith(SpringJUnit4ClassRunner.class) @ActiveProfiles("test") @ContextConfiguration(classes = {PersistenceConfigTest.class}) @Transactional @TransactionConfiguration(defaultRollback = true) @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class }) public class ProbeServiceImplTest { @Autowired private ProbeService probeService; @Test public void test() { Probe probe = ProbeFixtures.generateProbeSample("Test one"); probe.setGroup(ProbeFixtures.generateProbeGroupSample(1)); Probe saved = probeService.saveProbe(probe); System.out.println("Group name: " + saved.getGroup().getName()); } }
Entities:
@Entity @Table(name = "probes") public class Probe { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "probe_id") private long probeId; @Column(name = "probe_title", nullable = false) private String title; @Column(name = "probe_description", nullable = true) private String description; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "probe_group_id", nullable = true) private ProbeGroup group; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "probe_image_id", nullable = true) private ProbeFile image; @Column(name = "probe_published_date", nullable = false) private Date published; @Column(name = "probe_last_updated_date", nullable = false) private Date updated; @Column(name = "probe_expire_date", nullable = false) private Date expires; @Column(name = "probe_is_active", nullable = false) private boolean isActive; @OneToMany(mappedBy = "probe", fetch = FetchType.LAZY) private List<Question> questions; @OneToMany(mappedBy = "probe", fetch = FetchType.LAZY) private List<Vote> votes; public Probe() { questions = new LinkedList<>(); votes = new LinkedList<>(); } // getters & setters ... @Entity @Table(name = "probe_groups") public class ProbeGroup { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "probe_group_id") private long probeGroupId; @Column(name = "probe_group_name", nullable = false, unique = true) private String name; @Column(name = "probe_group_description", nullable = true) private String description; @OneToMany(mappedBy = "group", fetch = FetchType.LAZY) private List<Probe> probes; public ProbeGroup() { probes = new LinkedList<>(); } // getters & setters ...
And few last logs lines:
Hibernate: insert into probes (probe_description, probe_expire_date, probe_group_id, probe_image_id, probe_is_active, probe_published_date, probe_title, probe_last_updated_date) values (?, ?, ?, ?, ?, ?, ?, ?) Group name: null
I also tried to run spring data jpa method - getOne(id) after save(), but also it does not work (insert statement invoked, select not);
UPDATE: I removed @Transactional annotaion from my service and from test. Now when I'm saving an entity and then fetching the same entity, I have two sql statements in logs: insert and then select. Maybe my problem is because of wrong persistence/transaction configuration. What You think?