【问题标题】:Calling a function on insert with JDBC使用 JDBC 在插入时调用函数
【发布时间】:2021-11-27 22:53:26
【问题描述】:

我的 PostgreSQL 数据库中有以下函数和表:

CREATE OR REPLACE FUNCTION generate_uid(size INT) RETURNS TEXT AS $$
DECLARE
  characters TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  bytes BYTEA := gen_random_bytes(size);
  l INT := length(characters);
  i INT := 0;
  output TEXT := '';
BEGIN
  WHILE i < size LOOP
    output := output || substr(characters, get_byte(bytes, i) % l + 1, 1);
    i := i + 1;
  END LOOP;
  RETURN output;
END;
$$ LANGUAGE plpgsql VOLATILE;

create table users
(
    userid text primary key default generate_uid(50)
    , username varchar (50) not null
    , pass varchar (50) not null
    , firstname varchar (100) not null
    , lastname varchar (100) not null
    , email varchar (150) not null
    , roleid int not null
    , constraint fkrole foreign key(roleid) references userrole(roleid)
);

然后我用这段代码在 JDBC 中调用我的 DAO 中的函数:

Account A = new Account();
        String sha256hex = Hashing.sha256()
                  .hashString(password, StandardCharsets.UTF_8)
                  .toString();
        try (Connection conn = CustomClassFactory.getConnection()) {

            String sql = "INSERT INTO users (username, pass, firstname, lastname, email, roleid) VALUES (?,?,?,?,?,?)";
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, userName);
            ps.setString(2, sha256hex);
            ps.setString(3, firstName);
            ps.setString(4, lastName);
            ps.setString(5, email);
            ps.setInt(6, roleId);

            System.out.println(ps.toString());
            int i = ps.executeUpdate(); // <---update not query. this line is what sends the information to the DB
            if (i == 0) {
                System.out.println("Sorry, database was not updated. Returning to menu");
                return null;
            }

        } catch (SQLException e) {
            System.out.println("Sorry, database was not contacted. Bring your developer coffee. In the Insert Statement");
            e.printStackTrace();
            return null;
        }

我从堆栈跟踪中收到以下错误:

org.postgresql.util.PSQLException: ERROR: function gen_random_bytes(integer) does not exist
  Hint: No function matches the given name and argument types. You might need to add explicit type casts.
  Where: PL/pgSQL function generate_uid(integer) line 8 during statement block local variable initialization
    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.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:130)
    at dao.AccountDaoImp.CreateAccount(AccountDaoImp.java:35)
    at testing.Tester.main(Tester.java:11)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "models.Account.toString()" because the return value of "dao.AccountDaoImp.CreateAccount(String, String, String, String, String, int)" is null
    at testing.Tester.main(Tester.java:11)

当我创建一个新用户时,如何确保它能够看到该功能?该函数旨在生成一个随机文本字符串以用作唯一 ID。

【问题讨论】:

  • 我正在使用 dbeaver,除非我复制和粘贴,否则它不会让我保留正确的大小写。
  • 为什么不使用内置的uuid 类型而不是滚动您自己的“随机UID”?很可能也更快、更高效。

标签: postgresql jdbc java-11


【解决方案1】:

gen_random_bytes 是 pgcrypto 扩展的一部分。

所以在你的数据库中运行这个:

CREATE EXTENSION pgcrypto SCHEMA public;

为确保您不必依赖 search_path,您可以在函数调用前加上 public,就像在 public.gen_random_uuid() 中一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 2015-06-20
    • 2014-11-04
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多