It should work out of the box and I can't see anything directly wrong in the settings that you have provided. So my guess is that there is something additional here that is causing the problem (dependency, other setting etc.). You are using somewhat older versions of the Hibernate dialect and the JDBC driver, but that should not be the problem.
One possible problem could be that your system is not set up with default Google Cloud credentials. I noticed that your JDBC URL does not contain any credentials, which means that it will fallback to the default of the environment. I would expect an error if it could not find any, but it could be a possible cause of problems.
I've created a very simple test project with Spring boot and tried it out, and it does work. Could you try with this simple test setup as well and try to add from there to figure out where it goes wrong? Or otherwise give some more details on any additional dependencies that you may be including in your project?
My setup that works:
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>
Entity:
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;
}
}
Repository:
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 Application:
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