在java中将数据库从MySQL更改为PostgreSQL

Posted

技术标签:

【中文标题】在java中将数据库从MySQL更改为PostgreSQL【英文标题】:Changing database from MySQL to PostgreSQL in java 【发布时间】:2021-10-01 15:49:12 【问题描述】:

我之前用 mysql 运行我的 java 程序,一切都很好。现在我将程序连接到 PostgreSQL,但它给了我一些错误,我不知道我应该在哪里找到问题以及如何解决它。如果有人可以提供帮助,我将不胜感激。

我正在使用:

Java 15 春季启动 雄猫 9 PostgreSQL 13 PostgreSQL JDBC 42.2.23

为了运行 SQL 查询和创建数据库表,我使用了一个映射器存储库,它有一个带接口的抽象类,并且我为每个类定制了映射器。

这是我连接数据库的连接池:

import org.apache.commons.dbcp.BasicDataSource;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class ConnectionPool 
    private static BasicDataSource ds = new BasicDataSource();
    private final static String dbURL = "jdbc:postgresql://...:.../SomeThing? 
    characterEncoding=utf8";
    private final static String dbUserName = "...";

    private ConnectionPool() 
    

    static 
        ds.setDriverClassName("org.postgresql.Driver");
        // remote db
        ds.setUrl(dbURL);
        ds.setUsername(dbUserName);
        ds.setPassword(dbPassword);
        ds.setMinIdle(1);
        ds.setMaxIdle(2000);
        ds.setMaxOpenPreparedStatements(2000);
        setEncoding();
    

    public static Connection getConnection() throws SQLException 
        try 
            return ds.getConnection();
        catch (Exception e)
            ds.setPassword(dbPassword);
            return ds.getConnection();
        
    

    public static void setEncoding()
        try 
            Connection connection = getConnection();
            Statement statement = connection.createStatement();
            statement.execute("ALTER DATABASE ... CHARACTER SET utf8mb4 COLLATE 
            utf8mb4_unicode_ci;");
            connection.close();
            statement.close();
        
        catch (SQLException e)
        
        System.out.println(e.getMessage());
        
    

这是我的课程映射器类的示例:

public class CourseMapper extends Mapper<Offering, CustomPair> implements ICourseMapper 

    private static final String COLUMNS = " code, classCode, name, units, type, instructor, capacity, signedUp, start, end, time ";
    private static final String TABLE_NAME = "COURSES";

    public CourseMapper(Boolean doManage) throws SQLException 
        if (doManage) 
            Connection con = ConnectionPool.getConnection();
            Statement st = con.createStatement();
            st.executeUpdate(String.format("DROP TABLE IF EXISTS %s", TABLE_NAME));
            st.executeUpdate(String.format(
                    "create table %s (\n" +
                            "    code varchar(255) not null,\n" +
                            "    classCode varchar(255) not null,\n" +
                            "    name tinytext not null,\n" +
                            "    units int not null,\n" +
                            "    type tinytext not null,\n" +
                            "    instructor tinytext not null,\n" +
                            "    capacity int not null,\n" +
                            "    signedUp int not null default 0,\n" +
                            "    start tinytext not null,\n" +
                            "    end tinytext not null,\n" +
                            "    time tinytext not null,\n" +
                            "    primary key(code, classCode)\n" +
                            ");",
                    TABLE_NAME));
            st.close();
            con.close();
        
    

    public CourseMapper() throws SQLException 
    

    @Override
    protected String getFindStatement(CustomPair id) 
        return String.format("select * from %s where %s.%s = %s and %s.%s = %s", TABLE_NAME, TABLE_NAME, "code",
                StringUtils.quoteWrapper(id.getArgs().get(0)), TABLE_NAME, "classCode", StringUtils.quoteWrapper(id.getArgs().get(1)));
    

有了这个,我能够在 MySQL 数据库中创建表并实现查询(查找、插入、删除...)

但是,现在我想使用 PostgreSQL 数据库,通过运行项目它给了我这些错误:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "end"
      Position: 304
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2552)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2284)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:322)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:322)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:308)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:284)
    at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:258)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at com.internet.engineering.IECA5.repository.Course.CourseMapper.<init>(CourseMapper.java:24)
    at com.internet.engineering.IECA5.repository.MzRepository.createAllTables(MzRepository.java:35)
    at com.internet.engineering.IECA5.IeCa5Application.main(IeCa5Application.java:18)
org.postgresql.util.PSQLException: ERROR: type "tinytext" does not exist
      Position: 67
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2552)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2284)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:322)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:322)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:308)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:284)
    at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:258)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228)
    at com.internet.engineering.IECA5.repository.Student.StudentMapper.<init>(StudentMapper.java:22)

【问题讨论】:

这能回答你的问题吗? Escaping keyword-like column names in Postgres @tgdavies 你能告诉我它有什么帮助吗? MySql 和 postgresql,实际上所有的表服务器都使用不同的 SQL 语言方言。如果您从提供给我们的错误消息中删除详细的回溯,您将看到 postgresql 生成的两个语法错误。它不喜欢tinytext 数据类型,也不喜欢您命名为end 的列。尝试在交互式客户端程序中运行 SQL,然后再将其嵌入 Java 程序:这样调试更容易。 Postgres 和 mysql 的 sql 风格略有不同,在 mysql 中有效的 SQL 查询在 postgres 中可能无效,反之亦然。当您像这样编写查询时,它会使代码依赖于 db-vendor。尝试使用基于 JPA 的实现,以减少对数据库供应商的依赖。 varchar(255)代替tinytext怎么样? 【参考方案1】:

尽管所有主流关系数据库系统都使用 SQL,但它们都有自己的方言和其他偏离 ISO-9075 SQL 标准的怪癖。您不能只是将项目从 MySQL 转移到 PostgreSQL 并期望一切正常,尤其是数据类型。

堆栈跟踪显示了两个不同的问题:

    您有一个名为end 的列,而end 是reserved word in PostgreSQL(并且在SQL 标准中),所以它必须被引用才能用作列名:"end",或者在Java 中字符串\"end\"

    您使用名为 tinytext 的数据类型,它是 MySQL 特有的,在 PostgreSQL 中不存在。从 MySQL 文档来看,这最多允许 255 个字符,因此 VARCHAR(255) 可以用作替换(尽管给出了列的名称,看起来其中一些是持续时间、时间或日期时间值,所以你可能要考虑使用更合适的数据类型)。

请记住,您可能会在程序的其他地方遇到其他相关问题。 MySQL 因远离 SQL 标准而臭名昭著(尽管近年来有所改进),有时 MySQL 允许标准和大多数 SQL 方言不允许的事情。

【讨论】:

以上是关于在java中将数据库从MySQL更改为PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails 中将我的数据库从 SQLite 更改为 MYSQL

如何在 MySQL 中将 mediumtext 列更改为 varchar? (换表)

如何在 MySQL 中将默认 Null 更改为 NOT NULL

如何在 Node.js 中将字符串日期更改为时间戳?

如何使用Java在Spark中将数据库的列名更改为大写

在 DB2 中将数据类型从 DateTime 更改为 Time 会出错