programing

여러 데이터 소스를 구성한 후 JPA 명명 전략을 설정할 수 없음 (Spring 1.4.1 / Hibernate 5.x)

goodjava 2023. 3. 31. 22:22

여러 데이터 소스를 구성한 후 JPA 명명 전략을 설정할 수 없음 (Spring 1.4.1 / Hibernate 5.x)

휴지 상태 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

설정하는 복수의 데이터 소스 중 하나의 이름이 되기 때문에, 「삼촌」으로 설정했습니다.Spring 문서에 의하면, 이 데이터 소스를 다음과 같이 설정했습니다.

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

이 시점에서는 모든 것이 잘 진행되었다.

작성했습니다.@Entity아무 것도 없는 수업@Column예를 들어 자바 속성이 있는 경우 Hibernate가 컬럼 이름을 알아내도록 합니다.idBank하이버네이트는 자동으로 컬럼 이름을 다음과 같이 가정합니다.id_bankddl 생성, 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 문서도 참조할 수 있습니다.두 번째 데이터 소스를 정의하면 기본 콩을 구성할 수 없기 때문에 자체 데이터 소스를 정의해야 합니다.EntityManager그리고.TransactionManager위에서 설정한 데이터 소스와 더불어 다음 구성을 추가했습니다.

@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 열 이름을 snake case name으로 변환하는 암묵적인 명명 전략이 상실되었습니다.따라서 Java 속성이 있는 경우idBank열 이름을 잘못 사용합니다.idBank대신id_bank그 기능을 꼭 되찾고 싶습니다.

이에 대한 JPA 속성이 있습니다.spring.jpa.hibernate.naming-strategy스프링 및 휴지 상태에는 다음과 같은 다양한 명명 전략 클래스가 있습니다.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

하지만 이 중 어느 것도 효과가 없었다.

것 .를 들어 설정을 하는 방법이 있을 것 같습니다.★★★★★★★★★★★★★★★★★,SessionFactoryAPI를 사용합니다.이에 관한 문서에는 약간의 차이가 있는 것 같습니다.

정말 '아예'를 싶습니다.persistence.xml아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아.

그래서 나는 여기에 갇혔고 나는 누군가가 도와주기를 바란다.속성 을 디버깅하는 는 양쪽에서 .org.springframework ★★★★★★★★★★★★★★★★★」org.hibernate쓸만한 게 하나도 없었어요.이 콩이 설정되었을 때 코드를 조사하려고 했지만, 이 문제가 발생하는 장소를 찾을 수 없었습니다.만약 누군가가 그 정보를 가지고 있고 그것을 공유할 수 있다면 정말 감사하겠습니다.

동일한 문제가 발생하여 다음 코드로 수정했습니다(질문의 코드에 적용됨 - 단일 엔티티 관리자의 경우).

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

속성을 사용하면 @ewert answer와 같은 값을 얻을 수 있습니다.

# 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

최근 질문하신 바와 같이 기본 동작이 사라지는 이유를 설명할 수 있을 것 같습니다.

2.은 이 방식의 Spring Boot 2.됩니다.2에서 청각장애 설정은 다음 방법으로 실행됩니다.JpaBaseConfiguration:

    @Bean
    @Primary
    @ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
        Map<String, Object> vendorProperties = getVendorProperties();
        customizeVendorProperties(vendorProperties);
        return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan()).properties(vendorProperties)
                .mappingResources(getMappingResources()).jta(isJta()).build();
    }

그것은 안에서 일어난다.customizeVendorProperties메서드 콜

인 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★LocalContainerEntityManagerFactoryBean이 커스터마이즈는 더 이상 실행되지 않습니다.

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

언급URL : https://stackoverflow.com/questions/40509395/cant-set-jpa-naming-strategy-after-configuring-multiple-data-sources-spring-1