【问题标题】:Spring Data JPA: Fetching data from entity just after save() methodSpring Data JPA:在 save() 方法之后从实体中获取数据
【发布时间】:2014-10-17 05:12:09
【问题描述】:

我在我的项目中使用 Spring Data JPA 和 Hibernate JPA 提供程序。 在我的服务中,我有一个方法,它将实体保存在数据库中,而不是使用返回的对象,我尝试获取有关该实体的更多详细信息。 因此,不会获取详细信息。在日志中我只看到插入语句,没有选择详细信息。

这是我的代码:

配置:

@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
@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;
  }
}

简单测试:

@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());
  }
}

实体:

@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 ...

最后几行日志:

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

我也尝试过在save()之后运行spring data jpa方法-getOne(id),但是还是不行(insert statement调用,select not);

更新: 我从我的服务和测试中删除了@Transactional 注释。现在,当我保存一个实体然后获取同一个实体时,我在日志中有两个 sql 语句:插入然后选择。 也许我的问题是因为错误的持久性/事务配置。你怎么看?

【问题讨论】:

  • 我遇到了类似的问题:我的事务日志是通过触发器更新的,并且日志条目是建模实体,但是在 saveAndFlush() 之后没有加载关系,所以我必须传递 ID并获取好像我还没有对象一样。耶春天。
  • 第一:不要在 Spring(数据)测试中使用事务注解。 Spring 为您创建一个事务并回滚该事务。第二:物理刷新发生在提交之后。带有 Transactional 注释的方法将在离开方法后提交(如果此方法没有引发异常)。
  • 请写下你是如何解决这个问题的。

标签: java spring hibernate jpa spring-data-jpa


【解决方案1】:

这可能有点过时了,但我遇到了同样的问题,发现问题是休眠二级缓存。

【讨论】:

    【解决方案2】:

    save() 方法可能会也可能不会立即将您的更改写入数据库。如果要立即提交更改,则需要使用T saveAndFlush(T entity) 方法。

    【讨论】:

    • 还是不行。当我询问实体详细信息时,我得到了空值。当我在 save() 之后尝试在日志中执行 findOne(id) 方法时,我只看到没有 select 的插入语句。
    【解决方案3】:

    打印语句返回 null,因为只有 getName() 返回 null。 这意味着您的数据正在被保存,并且对象被返回。如果“保存”的对象为空,它应该抛出一个空指针异常。

    【讨论】:

    • 是的,我知道但如何获取这些数据:saved.getGroup().getName() 来自我的服务方法 saveProbe(Probe probe)。正如您在测试方法中看到的那样,我在保存之前填写了所有必要的数据。
    • @bhop "如你所见..." - 不,我们不能。我们只能看到你调用了一些方法。我们不知道他们实际上在做什么。就此而言,我们也看不到实体。
    • 对不起 :)。现在你真的可以看到我的实体了
    猜你喜欢
    • 2020-03-26
    • 1970-01-01
    • 2014-10-20
    • 2019-05-28
    • 2021-06-08
    • 2018-01-11
    • 2020-03-17
    • 1970-01-01
    • 2019-01-07
    相关资源
    最近更新 更多