Parece que esta é uma combinação de um "bug" do Spring e um "bug" do driver.
O Spring tenta determinar o tipo de dados de uma coluna toda vez que
setValue()
é chamado. Ele faz isso chamando PreparedStatementMetaData.getParameterMetaData()
Isso aparentemente faz com que uma instrução "prepare" seja enviada para o banco de dados, o que em si é bastante rápido (nunca mais de 1 ms no meu laptop), mas como é chamado para cada coluna para cada linha isso soma muito tempo (é chamado para cada valor não nulo que resulta em aproximadamente 23.000 chamadas)
Até certo ponto, isso é mais um bug do Spring do que um bug do driver, porque não armazenar em cache os metadados do parâmetro realmente não faz sentido (pelo menos na minha opinião). O driver MySQL JDBC não suporta
getParameterMetaData()
e o Spring sabe disso e, portanto, esse "bug" não aparece com o MySQL porque o Spring nunca chama esse método. Não tenho certeza se o comportamento do driver JDBC do Postgres pode ser classificado como um bug, mas com certeza seria bom se o driver estivesse armazenando em cache esses metadados após a primeira chamada.
O Spring pode ser convencido a não obter os metadados da instrução através da propriedade
spring.jdbc.getParameterType.ignore
Então colocando:
System.setProperty("spring.jdbc.getParameterType.ignore", "true");
antes a linha:
LetsGo letsGo = new LetsGo();
este comportamento está desabilitado.
A propriedade deve ser definida antes Spring é inicializado.
Quando faço isso com seu projeto de exemplo, a inserção é executada em 500ms no meu laptop.
Editar
Depois de ver o comentário sobre o uso do driver Postgres-NG, pesquisei nas fontes do driver "oficial" e do driver NG, e o driver NG armazena em cache os metadados do parâmetro após a primeira chamada, enquanto o driver oficial não explica por que usar o driver NG é muito mais rápido (sem desabilitar a chamada no Spring)