Интеграция Spring Data JPA с GCP Spanner - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь перенести существующее приложение весенней загрузки из Postgres в GCP Spanner.

Я использую следующий драйвер Cloud Spanner JDB C и диалект Hibernate:

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-hibernate-dialect</artifactId>
    <version>0.1.0</version>
</dependency>
<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-jdbc</artifactId>
    <version>1.7.0</version>
</dependency>

Также я настроил следующие свойства:

spring.datasource.url=jdbc:cloudspanner:/projects/YOUR_PROJECT_ID/instances/demo/databases/demo
spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver
spring.jpa.database-platform=com.google.cloud.spanner.hibernate.SpannerDialect

Однако при запуске приложения, которое зависает при попытке установить соединение с пулом:

o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2729 ms
com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Driver does not support get/set network timeout for connections. (Network timeout is not supported)

Поддерживает ли HikariCP GCP Spanner?

1 Ответ

1 голос
/ 25 марта 2020

Это должно работать из коробки, и я не вижу ничего неправильного в настройках, которые вы указали. Поэтому я предполагаю, что здесь есть что-то дополнительное, что вызывает проблему (зависимость, другие настройки и т. Д. c.). Вы используете несколько более старые версии диалекта Hibernate и драйвера JDB C, но это не должно быть проблемой.

Одной из возможных проблем может быть то, что ваша система не настроена с учетными данными Google Cloud по умолчанию. Я заметил, что ваш URL JDB C не содержит никаких учетных данных, что означает, что он будет откат к стандартному окружению. Я мог бы ожидать ошибки, если не смог найти ни одной, но это могло быть возможной причиной проблем.

Я создал очень простой тестовый проект с загрузкой Spring и опробовал его, и он работает. Не могли бы вы попробовать эту простую тестовую настройку и попытаться добавить оттуда, чтобы выяснить, где она идет не так? Или иначе дайте более подробную информацию о любых дополнительных зависимостях, которые вы можете включить в ваш проект?

Моя настройка, которая работает:

pom. xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.google.cloud</groupId>
  <artifactId>spanner-example-runner</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>spanner-example-runner</name>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner-jdbc</artifactId>
      <version>1.15.0</version>
    </dependency>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner-hibernate-dialect</artifactId>
      <version>1.1.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

Объект:

package com.google.cloud.example;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "SINGERS")
public class Singer {

  @Id private Long singerId;

  private String firstName;

  private String lastName;

  public Singer() {}

  public Singer(long singerId, String firstName, String lastName) {
    this.singerId = singerId;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public Long getSingerId() {
    return singerId;
  }

  public void setSingerId(Long singerId) {
    this.singerId = singerId;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

Репозиторий:

package com.google.cloud.example;

import java.util.List;
import org.springframework.data.repository.CrudRepository;

public interface SingerRepository extends CrudRepository<Singer, Long> {

  List<Singer> findByLastName(String lastName);

  Singer findById(long id);
}

Приложение Spring Boot:

package com.google.cloud.example;

import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class AccessingDataJpaApplication {
  private static final Logger log = LoggerFactory.getLogger(AccessingDataJpaApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(AccessingDataJpaApplication.class, args);
  }

  @Bean
  public CommandLineRunner demo(SingerRepository repository) {
    return (args) -> {
      // save a few singers
      repository.save(new Singer(10, "Jack", "Bauer"));
      repository.save(new Singer(20, "Chloe", "O'Brian"));
      repository.save(new Singer(30, "Kim", "Bauer"));
      repository.save(new Singer(40, "David", "Palmer"));
      repository.save(new Singer(50, "Michelle", "Dessler"));

      // fetch all singers
      log.info("Customers found with findAll():");
      log.info("-------------------------------");
      for (Singer customer : repository.findAll()) {
        log.info(customer.toString());
      }
      log.info("");

      // fetch an individual singer by ID
      Singer customer = repository.findById(1L);
      log.info("Customer found with findById(1L):");
      log.info("--------------------------------");
      log.info(customer.toString());
      log.info("");

      // fetch singers by last name
      log.info("Customer found with findByLastName('Bauer'):");
      log.info("--------------------------------------------");
      repository.findByLastName("Bauer").forEach(bauer -> {
        log.info(bauer.toString());
      });
      log.info("");
      // Cleanup
      repository.deleteById(10L);
      repository.deleteById(20L);
      repository.deleteById(30L);
      repository.deleteById(40L);
      repository.deleteById(50L);
    };
  }

  @Bean
  public PhysicalNamingStrategy physical() {
      return new PhysicalNamingStrategyStandardImpl();
  }

  @Bean
  public ImplicitNamingStrategy implicit() {
      return new ImplicitNamingStrategyLegacyJpaImpl();
  }
}

application.properties:

spring.datasource.url=jdbc:cloudspanner:/projects/my-project-id/instances/some-instance/databases/some-db?credentials=/path/to/credentials.json
spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver
spring.jpa.database-platform=com.google.cloud.spanner.hibernate.SpannerDialect
...