java - 如何使用原生sql获取现有表

标签 java hibernate spring-boot jpa

首先,对您可能犯的语法错误表示歉意。我的英语不是很好。

我创建了一个动态表生成器。我使用该表生成器动态创建具有不同 JSON 属性的表。

我完美地创建了表,但我想在创建之前检查它是否已经存在。

我使用sql sentence这适用于 pgAdmin,但是,当我在我的方法上使用这句话时,它不起作用。

我正在使用 sprong boot(JPA + hibernate)和 Postgresql。

它返回下一个错误:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: information_schema.tables is not mapped

如何获取所有已经存在的表?

这是我的代码:

@Service
@Transactional
public class TableGeoJsonGenerator {

    private static final Logger LOGGER = LogManager.getLogger(SchemeService.class);

    @Autowired
    private EntityManager em;

    public String initTable(String name, List<String> columns, List<String> typeColumns, ArrayList<Object> rows) {
        String nameTableFinal = "";
        if (!chekifExistTable(name)) {
            nameTableFinal = name;
            createTableWithColumns(name, columns, typeColumns);
        } else {
            UUID uuid = UUID.randomUUID();
            nameTableFinal = name + "-" + uuid.toString();
            createTableWithColumns(name, columns, typeColumns);
        }
        return nameTableFinal;
    }

    private void createTableWithColumns(String name, List<String> columns, List<String> typeColumns) {
        String SQL = "CREATE TABLE IF NOT EXISTS " + name + "( name_id varchar(255) ,table_id SERIAL, " + generateSqlColumns(columns, typeColumns) +" primary key (name_id));";
        executeSQL(SQL);
    }

    private String generateSqlColumns(List<String> columns, List<String> typeColumns) {
        String DINAMIC_COLUMNS = "";
        for (int i=0; i<columns.size(); i++) {
            DINAMIC_COLUMNS += columns.get(i).toString() + " " + getPostgresqlValue(typeColumns.get(i).toString()) + ", ";
        }
        return DINAMIC_COLUMNS;
    }

    private void executeSQL(String SQL) {
        try {
            Query query = em.createNativeQuery(SQL);
            query.executeUpdate();              
        } catch(Throwable e) {
            LOGGER.error(e.getMessage());
            throw e;
        } finally {
            em.close();
        }
    }

    private boolean executeSQLWithResults(String SQL, String nameTable) {
        boolean found = false;
        try {
            TypedQuery<?> lQuery = (TypedQuery<?>) em.createQuery(SQL);
            List<?> list = lQuery.getResultList();
            for (Object result : list) {
                LOGGER.debug(result.toString());
            }
            found = true;
        } catch(Throwable e) {
            LOGGER.error(e.getMessage());
            throw e;
        } finally {
            em.close();
        }
        return found;
    }

    private boolean chekifExistTable(String name) {
        String SQL = "select table_name from information_schema.tables where table_schema = 'public'";
        return executeSQLWithResults(SQL, name);
    }

    private String getPostgresqlValue(String value) {
        if (value.equals(Integer.class.toString())) {
            return "int8";
        } 
        else if (value.equals(Double.class.toString())) {
            return "float8";
        }
        else if (value.equals(String.class.toString())) {
            return "varchar(255)";
        }
        else if (value.equals(Long.class.toString())) {
            return "bigint";
        }
        else if (value.equals(Boolean.class.toString())) {
            return "boolean";
        }
        else if (value.equals(Date.class.toString())) {
            return "timestamp";
        }
        else {
            return "numeric";
        }       
    }

}

Amer Qarabsa 解决的解决方案:

private boolean executeSQLWithResults(String SQL, String nameTable) {
        boolean found = false;
        try {
            Query query = em.createNativeQuery(SQL);
            List<?> list = query.getResultList();
            for (Object result : list) {
                LOGGER.debug(result.toString());
            }
            found = true;
        } catch(Throwable e) {
            LOGGER.error(e.getMessage());
            throw e;
        } finally {
            em.close();
        }
        return found;
    }

最佳答案

Hibernate 会提示,因为您尝试访问 information_schema.tables 的对象未映射到实体。

问题出在这个方法

 private boolean chekifExistTable(String name) {
        String SQL = "select table_name from information_schema.tables where table_schema = 'public'";
        return executeSQLWithResults(SQL, name);
    }

在executeSQLWithResults中,您正在调用em.createQuery,createQuery需要JQL而不是SQL,因此这就是hibernate尝试将其映射到实体的原因,请检查link ,而是在其他方法executeSQL中使用相同的em.createNativeQuery

关于java - 如何使用原生sql获取现有表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57089916/

相关文章:

java - 需要一个用于 Java 控制台应用程序的假数据生成器

java - Hibernate 使用条件执行更新

java - 如何使用 Hibernate 插入新项目?

java - 如何动态限制Spring Security中的路由?

java - 如何在 Spring MVC JavaEE 中重定向到另一个站点

java - 管道<I/O>流。我可以传递复杂的对象吗?

java - Codename One 中 List<Date> 的其他排序方式

java - Hibernate/MySQL 连接超时——尝试处理退出后不释放 Hibernate 连接到 C3P0 的线程池执行程序

java - 测试单元 Spring Boot : Unable to register mock bean

java - 添加 HttpServletResponse/HttpServletRequest 作为方法参数时 Spring 请求挂起