【问题标题】:Spring JPA Specify entity's table name on the repository interfaceSpring JPA 在存储库接口上指定实体的表名
【发布时间】:2016-11-04 13:26:19
【问题描述】:

我有一个场景,我想为同一个实体类创建多个存储库。 第一个也是最简单的场景我想将我的类的一些实例保存为与主表(在实体本身上指定)不同的表中的行。 其他情况是创建远程备份,因此整个数据源会有所不同。 Spring 允许这样的事情吗?

【问题讨论】:

  • 我写了一个类似问题的答案(除了 spring-data-mongo):stackoverflow.com/questions/38337453/…
  • 链接有帮助吗?你还在寻找答案吗?
  • 我还没有尝试过 - 我正在修复我系统中的一些其他问题。今晚我会努力解决这个问题。谢谢
  • 嗨@Alex 抱歉,我花了一段时间才解决这个问题。您引用的链接是关于引用不同的数据库(特定于 MongoDB),但其他一切都是一样的。我的问题更多是围绕同一个数据库,但我需要引用不同的表。我看不到如何在存储库中指定表名。!所以本质上,相同的类实例可以驻留在两个不同的表中。
  • @Alex 我发现这可能是一个解决方案 SecondaryTables

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


【解决方案1】:

我不确定你会想要这个,但无论如何它都在这里......我可以找到使用 Spring Data Repositories 的最佳方法如下:

(1a) 手动定义 2 个存储库 bean 以使用 2 个数据源:

@Bean
@Qualifier("db1")
public ModelJpaRepository modelJpaRepositoryDb1() {
    JpaRepositoryFactoryBean<ModelJpaRepository, Model, String> myFactory = new JpaRepositoryFactoryBean<ModelJpaRepository, Model, String>();
    myFactory.setRepositoryInterface(ModelJpaRepository.class);
    myFactory.setEntityManager(entityManagerFactory1().createEntityManager());
    myFactory.afterPropertiesSet();
    return myFactory.getObject();
}

@Bean
@Qualifier("db2")
public ModelJpaRepository modelJpaRepositoryDb2() {
    JpaRepositoryFactoryBean<ModelJpaRepository, Model, String> myFactory = new JpaRepositoryFactoryBean<ModelJpaRepository, Model, String>();
    myFactory.setRepositoryInterface(ModelJpaRepository.class);
    myFactory.setEntityManager(entityManagerFactory2().createEntityManager());
    myFactory.afterPropertiesSet();
    return myFactory.getObject();
}

(1b):定义2个数据源(由前面的存储库定义引用):

@Bean(name = "dataSource1")
public DataSource dataSource1() {
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName(...);
    bds.setUrl(...);
    bds.setUsername(...);
    bds.setPassword(...);
    return bds;
}

@Bean(name = "dataSource2")
public DataSource dataSource2() {
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName(...);
    bds.setUrl(...);
    bds.setUsername(...);
    bds.setPassword(...);
    return bds;
}

(1c):定义 2 个 entityManager - 每个数据源 1 个(由之前的存储库定义引用):

@Bean
public EntityManagerFactory entityManagerFactory1() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setDataSource(dataSource1());
    entityManagerFactory.setPersistenceUnitName("pu1");
    entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
    entityManagerFactory.setJpaProperties(jpaProperties());
    entityManagerFactory.afterPropertiesSet();
    return entityManagerFactory.getNativeEntityManagerFactory();
}

@Bean
public EntityManagerFactory entityManagerFactory2() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setDataSource(dataSource2());
    entityManagerFactory.setPersistenceUnitName("pu2");
    entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
    entityManagerFactory.setJpaProperties(jpaProperties());
    entityManagerFactory.afterPropertiesSet();
    return entityManagerFactory.getNativeEntityManagerFactory();
}

(2) 注入 2 个存储库并使用它们:

@Autowired
@Qualifier("db1")
private ModelJpaRepository modelJpaRepositoryDb1;

@Autowired
@Qualifier("db2")
private ModelJpaRepository modelJpaRepositoryDb2;

...

modelJpaRepositoryDb1.save(model);
modelJpaRepositoryDb2.save(model);

(3) 定义“OtherModel”并将“Model”嵌入:

@Entity
@Table(name = "OTHER_TABLE")
public class OtherTable {

    @Id
    @Column(name = "ID", nullable = false)
    private long id;

    @Embedded
    private Model model;

    public OtherTable(Model model) {
        this.model = model;
        this.id = model.getId();
    }
}

供参考,This answer 建议使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 来实现定义附加模型(继承与组合)。

(4) 为 OtherTable 定义 2 个存储库:

@Bean
@Qualifier("db1")
public OtherTableJpaRepository otherTableJpaRepositoryDb1() {
    JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String> myFactory = new JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String>();
    myFactory.setRepositoryInterface(OtherTableJpaRepository.class);
    myFactory.setEntityManager(entityManagerFactory1().createEntityManager());
    myFactory.afterPropertiesSet();
    return myFactory.getObject();
}

@Bean
@Qualifier("db2")
public OtherTableJpaRepository otherTableJpaRepositoryDb2() {
    JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String> myFactory = new JpaRepositoryFactoryBean<OtherTableJpaRepository, OtherTable, String>();
    myFactory.setRepositoryInterface(OtherTableJpaRepository.class);
    myFactory.setEntityManager(entityManagerFactory2().createEntityManager());
    myFactory.afterPropertiesSet();
    return myFactory.getObject();
}

(5) 全部注入使用:

@Autowired
@Qualifier("db1")
private ModelJpaRepository modelJpaRepositoryDb1;

@Autowired
@Qualifier("db2")
private ModelJpaRepository modelJpaRepositoryDb2;

@Autowired
@Qualifier("db1")
private OtherTableJpaRepository otherTableJpaRepositoryDb1;

@Autowired
@Qualifier("db2")
private OtherTableJpaRepository otherTableJpaRepositoryDb2;

// ...

modelJpaRepositoryDb1.save(model);
otherTableJpaRepositoryDb1.save(new OtherTable(model));

modelJpaRepositoryDb2.save(model);
otherTableJpaRepositoryDb2.save(new OtherTable(model));

【讨论】:

  • 好的,谢谢,我会试试看的。我必须说它看起来超级复杂,因为我认为应该是一个正常的功能。我想知道人们将如何实现一种数据的历史值,一种以前版本的日志。我不知道。无论如何,非常感谢。我会告诉你的。
猜你喜欢
  • 2015-02-13
  • 2014-06-20
  • 1970-01-01
  • 2019-07-28
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
相关资源
最近更新 更多