JPA Hibernate Call Postgres Function Void Return MappingException:

前端 未结 7 2039
不知归路
不知归路 2020-12-31 11:38

I have a problem where I am getting an: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111 when trying to call a postgres function using JPA cre

相关标签:
7条回答
  • 2020-12-31 12:00

    Dude! It's as easy as quoting the function name. Like so:

    public void runRequestCleanup() {
        String queryString = "SELECT \"a_function_that_hibernate_chokes_on\"()";
        Query query = em.createNativeQuery(queryString);
        Object result = query.getSingleResult();
    }
    
    0 讨论(0)
  • 2020-12-31 12:07

    This was posted some time ago, but I had the similar issue. As stated, Hibernate looks allergic to void and will try to lock you into using the return type every time. From my point of view, this is a good practice as you should normally always have a return at least to specify if it succeeded: throwing exception is often abusive.

    Yet, Hibernate DOES offer a way to bypass it's limitations: org.hibernate.jdbc.Work

    You can easily reproduce what was required in a small class:

    class VoidProcedureWork implements Work {
    
        String query;
    
        private VoidProcedureWork(String sql) {
            query = sql;
        }
    
        public static boolean execute(Session session, String sql) {
            try {
                // We assume that we will succeed or receive an exception.
                session.doWork(new VoidProcedureWork(sql));
                return true;
            } catch (Throwable e) {
                // log exception
                return false;
            }
        }
    
        /** 
         * @see org.hibernate.jdbc.Work#execute(java.sql.Connection)
         */
        @Override
        public void execute(Connection connection) throws SQLException {
            Statement statement = null;
            try {
                statement = connection.createStatement();
                statement.execute(query);
            } finally {
                if (statement != null)
                    statement.close();
            }
        }
    }
    

    Now you can call it whenever you want by using

    VoidProcedureWork.execute(hibernateSession, sqlQuery);

    You will notice two things about this class: 1) I do NOT close the Connection. I leave it that way because I do not know who opened the Connection, how and why. Is the same connection used in a transaction? If I close it ant someone uses it after, will it crash? Etc. I did not code Hibernate and did not use connection.open(). Therefore, I do not close it and assume whatever opened it will close it too. 2) It is more procedural programming than OOP. I know, but I am lazy: it is easier (and clearer imo) to use VoidProcedureWork.execute(session, sql) than new VoidProcedureWork(sql).execute(session). Or even worst: reproduce the code of execute everytime I want to use that little trick (session.doWork(new VoidProcedureWork(sql)) with exception processing).

    0 讨论(0)
  • 2020-12-31 12:10

    Convert query to : SELECT cast(sqlFunction() as text) eg : "SELECT cast(pushlogsToMainTable() as text)" It worked for me.

    0 讨论(0)
  • 2020-12-31 12:17

    For future visitors of this issue, a cast would have worked too. posted on this thread as well

    public void runRequestCleanup() {
        String queryString = "SELECT cast(a_function_that_hibernate_chokes_on() as text)";
        Query query = em.createNativeQuery(queryString);
        query.getSingleResult();
    }
    
    0 讨论(0)
  • 2020-12-31 12:20

    It seems that the problem occurs when the postgres stored procedure returns void. Try to change the return type to return some dummy value, perhaps a string. This worked in my case.

    0 讨论(0)
  • 2020-12-31 12:22

    This could be a hack, but it worked for me and is pretty simple. Just change the query to:

    SELECT count(*) FROM your_function();
    

    Now it returns a proper integer and hibernate is happy.

    0 讨论(0)
提交回复
热议问题