web-dev-qa-db-ja.com

複数のデータソースを構成した後、JPAネーミング戦略を設定できない(Spring 1.4.1 / Hibernate 5.x)

Hibernate 5.0.11を使用するSpring Boot 1.4.1を使用しています。最初に、次のようにapplication.propertiesを使用してデータソースを構成しました。

spring.datasource.uncle.url=jdbc:jtds:sqlserver://hostname:port/db
spring.datasource.uncle.username=user
spring.datasource.uncle.password=password
spring.datasource.uncle.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.datasource.uncle.driverClassName=net.sourceforge.jtds.jdbc.Driver

「uncle」で構成しました。これは、構成する複数のデータソースの1つの名前になるためです。 Springのドキュメントに従って、私はこのデータソースを次のように構成しました:

@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.uncle")
public DataSource uncleDataSource() {
    return DataSourceBuilder.create().build();
}

この時点ですべてがうまくいきました。

@Entityアノテーションなしで@Columnクラスを作成し、Hibernateに列名を認識させます。たとえば、idBankという名前のJavaプロパティがある場合、Hibernateは自動的に列名はid_bankです。これは、ddlを生成したり、SQLステートメントを実行したりするときに使用されます。多くのエンティティークラスを作成するので、この機能を利用したいと思います。 @Columnアノテーションをすべて維持します。この時点で、これは問題なく機能しました。

次に、次のような別のデータソースを追加しました。

spring.datasource.aunt.url=jdbc:sybase:Tds:Host2:port/db2
spring.datasource.aunt.username=user2
spring.datasource.aunt.password=password2
spring.datasource.aunt.dialect=org.hibernate.dialect.SybaseDialect
spring.datasource.aunt.driverClassName=com.sybase.jdbc4.jdbc.SybDriver

...そしてまた、これは、複数のデータソースを設定するためのSpringドキュメントに従っています。どうやら2番目のデータソースを定義すると、デフォルトのBeanを構成できなくなり、独自のEntityManagerTransactionManagerを定義する必要があるようです。上記で構成したデータソースに加えて、次の構成を追加しました。

@Bean
@Primary
PlatformTransactionManager uncleTransactionManager(@Qualifier("uncleEntityManagerFactory") final EntityManagerFactory factory) {
    return new JpaTransactionManager(factory);
}

@Bean
@Primary
LocalContainerEntityManagerFactoryBean uncleEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(uncleDataSource())
            .packages(Uncle.class)
            .persistenceUnit("uncle")
            .build();
}

@Bean
@ConfigurationProperties(prefix = "spring.datasource.aunt")
public DataSource auntDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
PlatformTransactionManager auntTransactionManager(@Qualifier("auntEntityManagerFactory") final EntityManagerFactory factory) {
    return new JpaTransactionManager(factory);
}

@Bean
LocalContainerEntityManagerFactoryBean auntEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(auntDataSource())
            .packages(Aunt.class)
            .persistenceUnit("aunt")
            .build();
}

これは、データベースに接続してデータをフェッチしようとするという意味で機能します。

[〜#〜]ただし、[〜#〜](これが問題です。ここまで読んでくれてありがとう)これらの構成の後、Java列名を蛇のケース名に変換する暗黙の命名戦略を失ったため、JavaプロパティidBankがあると、誤って使用されますid_bankの代わりに列名idBankを使用します。この機能を元に戻したいのですが。

このspring.jpa.hibernate.naming-strategyにはJPAプロパティがあり、SpringおよびHibernateにはorg.springframework.boot.orm.jpa.hibernate.SpringNamingStrategyなどのさまざまな命名戦略クラスがあります。だから私はこのように設定してみました:

spring.jpa.hibernate.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy

しかし、それはうまくいきませんでした。私はいくつかのバリエーションを試しました:

spring.datasource.uncle.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy

そして

spring.datasource.uncle.hibernate.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy

しかし、これは効果がありませんでした。

次に、Hibernate 5で名前付け戦略が「物理的」と「暗黙的」の2つの部分に分けられ、それぞれに異なる設定があることを読みました。だから私はこれを試しました、いくつかのバリエーションがあります:

spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

そして

spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

そして

spring.datasource.uncle.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

そして

spring.datasource.uncle..hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

しかし、どれもうまくいきませんでした。

SessionFactoryなど、この設定を直接Beanに設定する方法があるはずですが、そのAPIが見つかりませんでした。この周りのドキュメントにはいくつかのギャップがあるようです。

persistence.xmlも設定しないでください。これまでは必要ありませんでした。

だから私はここで行き詰まっているので、誰かが助けてくれることを願っています。これらのプロパティ設定をデバッグする方法が本当に欲しいのですが、org.springframeworkorg.hibernateの両方でトレースログをオンにしましたが、何も役に立たなかったのです。これらのBeanが構成されているときにコードをステップ実行しようとしましたが、これが発生する場所が見つかりませんでした。もし誰かがその情報を持っていて、それを共有できたら、私は本当に感謝します。

29
Uncle Long Hair

私は同じ問題を抱えており、次のコードで修正しました(問題のコードに適応-単一のエンティティマネージャー用):

protected Map<String, Object> jpaProperties() {
    Map<String, Object> props = new HashMap<>();
    props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
    props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
    return props;
}

@Primary
@Bean(name = "defaultEntityManager")
public LocalContainerEntityManagerFactoryBean defaultEntityManagerFactory(
    EntityManagerFactoryBuilder builder) {
    return builder
        .dataSource(auntDataSource())
        .packages(Aunt.class)
        .persistenceUnit("aunt")
        .properties(jpaProperties())
        .build();
}
46
ewert

プロパティを使用して、@ ewertと同じ答えを得ることができます。

# this works
spring.jpa.properties.hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.properties.hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

# but that doesn't work
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
0
marioosh

SessionFactoryを使用している場合は、次の行を使用して命名戦略を設定する必要があります。

sessionFactory.setImplicitNamingStrategy(SpringImplicitNamingStrategy.INSTANCE);
sessionFactory.setPhysicalNamingStrategy(new SpringPhysicalNamingStrategy());

Spring-Boot 2+でこれを正しく実行する唯一の方法は、手動で以下を設定することでした。

  @Bean(name = "myEmf")
  public LocalContainerEntityManagerFactoryBean sapEntityManagerFactory(
      EntityManagerFactoryBuilder builder, @Qualifier("myDataSource") DataSource dataSource) {
    return builder
        .dataSource(dataSource)
        .packages("my.custom.package")
        .persistenceUnit("myPu")
        .properties(getProperties())
        .build();
  }

  public Map<String, String> getProperties() {
   val props = new HashMap<String, String>();

    if (isTest()) {
      props.put("hibernate.hbm2ddl.auto", "create");
    } else {
      props.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect");
    }
    return props;
  }
0
Jaumzera