连接现有的运行Spring Boot的Docker容器中的Postgres。

huangapple go评论101阅读模式
英文:

Wiring Up pre-existing Docker container running Postgres with Spring Boot

问题

My goal is: 使用运行Postgres数据库的Docker容器。使用该容器构建Spring服务和数据访问层。所有这些都在我的本地环境中进行。

我正在进行设置在Docker容器中运行Postgres数据库。我已经启动了容器。我已经创建了表、视图、触发器、序列等等。据我所知,一切都正常。我可以使用pgAdmin连接。

现在,我转向设置Spring Boot、Repository、Model以及单表的单元测试。该测试只向表中插入了几条记录。我尝试了几个示例、教程和博客,但在使用Maven构建和测试项目时,我收到了以下错误。

根据错误信息,我理解Spring Boot找不到表的序列,测试也无法证明容器正在运行。

以下是创建映像的方式:

docker run --name plaid_postgres2 --rm -d -p 54321:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=ach postgres

这是环境设置的更多信息。

以下是我的应用程序属性设置:

# database connectivity
spring.jpa.open-in-view=true
spring.jpa.database=POSTGRESQL
spring.datasource.platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://localhost:54321/ach
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

这是实体声明。请注意,我在Postgres中为特定表使用了序列。

@Entity
@Table(schema = "investor", name="vendor_tbl")
public class Vendor  implements Serializable {
    // ...
}

这是我的测试类。

public class VendorRepositoryTest {
    // ...
}

在搜索了两天之后,我不知道如何解决问题。任何建议或指导将不胜感激。

谢谢,Russ

英文:

My goal is: Use a Docker container running a Postgres database. Use this container for building the Spring Services and data access layer. All of this is within my local environment.

I am working through setting up a Postgres database within a Docker container. I have the container up and running. I am have created the tables, views, triggers, sequences, etc. It works fine from all I can tell. I am able to connect using pgAdmin.

I have now moved to setting up Spring Boot, the Repository, the Model, and the unit test for a single table. The test only inserts a couple of records into the table. I have tried following several examples, tutorials and blogs.

When I build and test using maven for the project, I received the below error.

2020-08-10 16:01:49.407  INFO 83573 --- [           main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories…
2020-08-10 16:01:49.771  INFO 83573 --- [           main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-08-10 16:01:49.789  INFO 83573 --- [           main] n.c.p.s.repository.VendorRepositoryTest  : Started VendorRepositoryTest in 6.623 seconds (JVM running for 7.917)
2020-08-10 16:01:49.932  INFO 83573 --- [           main] o.t.d.DockerClientProviderStrategy       : Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2020-08-10 16:01:50.660  INFO 83573 --- [           main] o.t.d.UnixSocketClientProviderStrategy   : Accessing docker with local Unix socket
2020-08-10 16:01:50.661  INFO 83573 --- [           main] o.t.d.DockerClientProviderStrategy       : Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
2020-08-10 16:01:50.816  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : Docker host IP address is localhost
2020-08-10 16:01:50.871  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : Connected to docker: 
  Server Version: 19.03.12
  API Version: 1.40
  Operating System: Docker Desktop
  Total Memory: 1991 MB
2020-08-10 16:01:51.966  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2020-08-10 16:01:51.966  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : Checking the system...
2020-08-10 16:01:51.967  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : ✔︎ Docker server version should be at least 1.6.0
2020-08-10 16:01:52.131  INFO 83573 --- [           main] org.testcontainers.DockerClientFactory   : ✔︎ Docker environment should have more than 2GB free disk space
2020-08-10 16:01:52.154  INFO 83573 --- [           main] 🐳 [postgres:9.6.12]                     : Creating container for image: postgres:9.6.12
2020-08-10 16:01:52.254  INFO 83573 --- [           main] 🐳 [postgres:9.6.12]                     : Starting container with ID: 0c1ea5de4bc47651ac2ce02d1e85590a9165d9c31b7584ea1924d88fc85eeaad
2020-08-10 16:01:52.614  INFO 83573 --- [           main] 🐳 [postgres:9.6.12]                     : Container postgres:9.6.12 is starting: 0c1ea5de4bc47651ac2ce02d1e85590a9165d9c31b7584ea1924d88fc85eeaad
2020-08-10 16:01:57.539  INFO 83573 --- [           main] 🐳 [postgres:9.6.12]                     : Container postgres:9.6.12 started in PT7.619S
Hibernate: select nextval ('vendor_tbl_vendor_id_seq')
2020-08-10 16:01:57.587 ERROR 83573 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: relation "vendor_tbl_vendor_id_seq" does not exist
  Position: 17
Hibernate: select vendor0_.id as id1_0_, vendor0_.vendor_env as vendor_e2_0_, vendor0_.lpl_client_id as lpl_clie3_0_, vendor0_.public_key as public_k4_0_, vendor0_.secret_key as secret_k5_0_, vendor0_.vendor_name as vendor_n6_0_ from investor.vendor_tbl vendor0_
[ERROR] Tests run: 3, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 15.57 s <<< FAILURE! - in net.clouddeveloper.plaid.services.repository.VendorRepositoryTest
[ERROR] addVendor  Time elapsed: 8.052 s  <<< ERROR!
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
        at net.clouddeveloper.plaid.services.repository.VendorRepositoryTest.addVendor(VendorRepositoryTest.java:84)
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
        at net.clouddeveloper.plaid.services.repository.VendorRepositoryTest.addVendor(VendorRepositoryTest.java:84)
Caused by: org.postgresql.util.PSQLException: 
ERROR: relation "vendor_tbl_vendor_id_seq" does not exist
  Position: 17
        at net.clouddeveloper.plaid.services.repository.VendorRepositoryTest.addVendor(VendorRepositoryTest.java:84)

[ERROR] validateDatabaseRunning  Time elapsed: 0.005 s  <<< ERROR!
java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
        at net.clouddeveloper.plaid.services.repository.VendorRepositoryTest.performQuery(VendorRepositoryTest.java:56)
        at net.clouddeveloper.plaid.services.repository.VendorRepositoryTest.validateDatabaseRunning(VendorRepositoryTest.java:46)

From what I understand from the error, Spring Boot can not find the sequence for the table and the test can not prove can not prove the container is running.

连接现有的运行Spring Boot的Docker容器中的Postgres。
Here is how I create the image:

docker run --name plaid_postgres2 --rm -d -p 54321:5432 -e POSTGRES_PASSWORD=postgres  -e POSTGRES_DB=ach  postgres 

This is more of the environment settings.
连接现有的运行Spring Boot的Docker容器中的Postgres。

Here is how I have the application properties setup:

# database connectivity
spring.jpa.open-in-view=true
spring.jpa.database=POSTGRESQL
spring.datasource.platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://localhost:54321/ach
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

This is the Entity declaration. Note I am using a sequence in Postgres for the specific table.

@Entity
@Table(schema = "investor", name="vendor_tbl")
public class Vendor  implements Serializable {


    private static final long serialVersionUID = -2343243243242432341L;
    @Id
    @Column(name="vendor_id")
    @SequenceGenerator(schema="investor",
                       name="vendor_tbl_vendor_id_seq",
                       sequenceName="vendor_tbl_vendor_id_seq",
                       allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,  generator="vendor_tbl_vendor_id_seq")
    private long vendor_id;

This is my Test Class:

public class VendorRepositoryTest {

    @Autowired
    private VendorRepository repository;


   @Container
    private static final PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer()
            .withDatabaseName("ach")
            .withUsername("postgres")
            .withPassword("postgres");


    @Test
    @DisplayName("Validate Database is Running")
    void validateDatabaseRunning() throws Exception {
        ResultSet resultSet = performQuery(postgresqlContainer, "SELECT 1");
        resultSet.next();
        int result = resultSet.getInt(1);
        assertEquals(1, result);

        assertTrue(postgresqlContainer.isRunning());
    }

    private ResultSet performQuery(PostgreSQLContainer protgres, String query) throws SQLException {

        String jdbcURL = postgresqlContainer.getJdbcUrl();
        String userName = postgresqlContainer.getUsername();
        String password = postgresqlContainer.getPassword();
        Connection conn = DriverManager.getConnection(jdbcURL, userName, password);
        return conn.createStatement().executeQuery(query);

    }


    @Test
    @DisplayName("Test Find All Vendors")
    public void find_all_vendors() {
        Iterable<Vendor> vendors = repository.findAll();

        int numOfCities =4;
        assertThat(vendors).isEmpty(); //.hasSize(numOfCities);
    }

    @Test
    @DisplayName("Test Add Vendor")
    public void addVendor(){
        String clientID = "blahblahblah";
        String secret_key = "blahblah";
        String public_key = "blahblah";
        String environment = "blah";
        String vendor_name = "Russ Test";
        Vendor vendor1 = new Vendor(clientID, secret_key, public_key, environment, vendor_name);
        Vendor vendor2 = new Vendor(clientID, secret_key, public_key, environment, vendor_name);
        this.repository.save(vendor1);
        this.repository.save(vendor2);
    }


}

After of two days of searching for answers, I have lost direction on how to resolve. Any suggestions or guidance would be greatly appreciated.

Thanks,

Russ

答案1

得分: 1

以下是翻译好的部分:

不必使用Dockerfile,但您需要定义并传递给Docker容器的用户名、密码和数据库名称。您也可以在运行命令中执行此操作:

docker run --rm --name postgresContainer -d -p 54320:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=yourDatabase postgres

默认用户名是postgres,所以您不需要指定它。命令中的最后一个postgres单词是镜像的名称。

我还将yourDatabase命名为不同的名称,因为我认为postgres中有一个默认的数据库叫做postgres。

在运行上述命令后,您可以执行以下命令来检查您的数据库是否正在运行:

docker exec -it postgresContainer bash

su postgres

psql

\list

这将显示所有可用的数据库。现在键入:

\c yourDatabase

然后您已连接到postgres Docker中的数据库。随时运行创建表/选择或其他操作。

要退出,只需键入\qexit,然后再次键入。容器将继续运行。


不要忘记更新您的Spring属性以匹配:

spring.datasource.url=jdbc:postgresql://localhost:54320/yourDatabase
spring.datasource.username=postgres
spring.datasource.password=postgres

此外,我认为您应该从您的Java代码中删除schema参数,我从未使用过它,我担心它会开始搜索'investor'数据库。

英文:

You don't have to use Dockerfile but you need to define and pass to Docker container username, password and database name. You could do that also in the run command:

docker run --rm --name postgresContainer -d -p 54320:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=yourDatabase postgres

default username is postgres so you don't need to specify that. Last postgres word in command is the name of the image

I also called yourDatabase differently because I think there is a default database in postgres called postgres.

After running the above command you can execute the following to check that your database is running:

docker exec -it postgresContainer bash

su postgres

psql

\list

This will show you all of the databases available. Now type:

\c yourDatabase

and you are connected to your database in postgres Docker. Feel free to run create tables/selects or whatever.

to exit just type \q and exit like 2 times. Container will keep running.


Don't forget to update you spring properties to match

spring.datasource.url=jdbc:postgresql://localhost:54320/yourDatabase
spring.datasource.username=postgres
spring.datasource.password=postgres

also I think you should remove the schema parameter from your java code, I never used it and I am afraid it will start searching for 'investor' database.

huangapple
  • 本文由 发表于 2020年8月11日 04:21:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63347474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定