【问题标题】:Spring - Data persisted by JdbcTemplate unable to be seen by JpaRepositorySpring - JdbcTemplate 保存的数据无法被 JpaRepository 看到
【发布时间】:2017-05-09 09:20:06
【问题描述】:

我正在构建一个 Spring Boot 应用程序,该应用程序需要通过 JDBC 持久化并通过 JPA/Hibernate 进行选择/读取。我已经使用 Spring 的 JdbcTemplate 和 Spring Data 的 JpaRepository 实现了这两种类型的操作。

在我坚持使用 JdbcTemplate 后,我无法通过 JpaRepository 查看数据,即使它们共享相同的数据源。如果我使用 JdbcTemplate,我可以读取数据。

注意:我正在使用两个数据源。一个是在另一个类中配置的,没有使用它自己的实体管理器工厂和事务管理器的 @Primary 注释,这就是为什么我需要使用 Spring Boot 的默认 bean 术语“transactionManager”和“entityManagerFactory”在下面显式定义它。

以下是我的主 bean 的嵌入式数据库配置:

@Configuration
@EnableJpaRepositories(basePackages = {"com.repository"})
public class H2DataSourceConfiguration {

    private static final Logger log = LoggerFactory.getLogger(H2DataSourceConfiguration.class);

    @Bean(destroyMethod = "shutdown")
    @Primary
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .setName("dataSource")
                .build();
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) { 
        return builder
            .dataSource(dataSource)
            .packages("com.my.domain", "org.springframework.data.jpa.convert.threeten")
            .build();
    }

    @Bean
    @Primary
    public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(entityManagerFactory);
        return jpaTransactionManager;
    }
}

持久性发生在与读取数据不同的事务中,但是它们共享相同的服务。 这两个操作都发生在 @Transactional 注释中。两个存储库 bean 都在同一个服务中指定,并且还包含 @Transactional 注释。该服务如下所示:

@Service
@Transactional
public class MyServiceImpl implements MyService {

    private static final Logger log = LoggerFactory.getLogger(MyServiceImpl.class);

    @Autowired
    private MyJpaRepository myJpaRepository;

    @Autowired
    private MyJdbcRepository myJdbcRepository;

    ...
}

MyJdbcRepositoryImpl.java:

@Repository
@Transactional(propagation = Propagataion.MANDATORY)
public class MyJdbcRepositoryImpl implements MyJdbcRepository {

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;

   // methods within here all use jdbcTemplate.query(...)
}

MyJpaRepository.java:

@Repository
@Transactional(propagation = Propagataion.MANDATORY)
public interface AcquisitionJpaRepository extends JpaRepository<AcquisitionEntity, Long> {

}

jdbctemplate 调用是否有可能保存到不同的 h2 数据库?

【问题讨论】:

  • 我会打开登录 hibernate 以显示 SQL,并将从 JPA 存储库运行的 hibernate 生成的 SQL 与您手动编写的 JDBC 模板代码进行比较。您能否也发布您的持久性和查询代码。很想知道您为什么坚持使用手动 JDBC。
  • 您没有为 LocalContainerEntityManagerFactoryBean 指定任何供应商适配器。可能是这个原因
  • 您无法阅读它的事实可能意味着您尚未提交它或有 2 个事务。您不能从另一个事务中读取未提交的数据。另外,如果您使用的是 Spring Boot,为什么要手动配置?
  • 为什么要手动创建JpaTransactionManager?看起来您有两个独立的交易。
  • @PaulNUK 坚持使用 JDBC,因为我们的音量级别需要它的速度。使用 JPA 阅读,因为我们需要流式传输一些结果并对其他结果进行分页。

标签: spring jdbc spring-boot transactions spring-data-jpa


【解决方案1】:

以上配置正确!

问题在于 JdbcTemplate 调用将架构所有者作为前缀。 例如:

select * from I_AM_SCHEMA.KILL_ME

但是,我在实体对象上同时使用了@Entity 注释和@Table 注释,并且只指定了表名! 示例:

@Entity
@Table(name = "KILL_ME")

因此,我们使用 JdbcTemplate 写入一个表,但由于我们缺少前缀,因此通过 JPA/Hibernate 从另一个完全不同的表读取。

正确的解决方法是在 @Entity 注释中为实体名称添加前缀:

@Entity("I_AM_SCHEMA.KILL_ME")

完成!

【讨论】:

    猜你喜欢
    • 2021-02-02
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2012-10-05
    • 2017-05-24
    • 1970-01-01
    相关资源
    最近更新 更多