【问题标题】:How SpringBoot JPA run DDL sql with dynamic tableName?Spring Boot JPA 如何使用动态表名运行 DDL sql?
【发布时间】:2019-10-23 08:53:58
【问题描述】:

是的,我有这个问题,jpa如何使用动态表名运行DDL sql? 通常,我只使用 DQL 和 DML,例如“选择、插入、更新、删除”。 如:

public interface UserRepository extends JpaRepository<User, Integer> {

    @Query(value = "select a.* from user a where a.username = ? and a.password = ?", nativeQuery = true)
    List<User> loginCheck(String username, String password);

}

但是当我需要在下面运行 DDL sql 时

String sql = "create table " + tableName + " as select * from user where login_flag = '1'";

我找不到使用 Jpa(或 EntityManager)解决此问题的方法。 最后我用JDBC来运行DDL sql,但我觉得它很难看...

Connection conn = null;
PreparedStatement ps = null;
String sql=" create table " + tableName + " as select * from user where login_flag = '1' ";
try {
    Class.forName(drive);
    conn = DriverManager.getConnection(url, username, password);
    ps = conn.prepareStatement(sql);
    ps.executeUpdate();
    ps.close();
    conn.close();
} catch (Exception e) {
    e.printStackTrace();
}

那么,jpa 能否用动态表名轻松运行 DDL sql(如 CREATE/DROP/ALTER)?

【问题讨论】:

    标签: jpa spring-data-jpa spring-boot-jpa


    【解决方案1】:

    您的问题似乎由两部分组成

    第一部分

    jpa 可以运行 DDL sql

    当然,只需使用entityManager.createNativeQuery("CREATE TABLE ...").executeUpdate()。这可能不是最好的主意(您应该使用像 Flyway 或 Liquibase 这样的数据库迁移工具来创建数据库),但它会起作用。

    请注意,您可能会遇到一些问题,例如不同的 RDBMS 对围绕 DDL 语句的事务有不同的要求,但大多数时候可以很容易地解决它们。

    您可能想知道在使用 Spring Data 时如何获取EntityManager。有关如何创建自定义存储库片段的说明,请参阅here,您可以在其中注入几乎任何您需要的东西。

    第二部分

    使用动态表名

    JPA 仅支持查询中某些子句中的参数,标识符不是其中之一。恐怕你需要使用字符串连接。

    为什么要动态表名呢?这不像您的实体定义会在运行时更改。静态 DDL 脚本通常不易出错。

    【讨论】:

    • 我尝试了entityManager.createNativeQuery("CREATE TABLE ...").executeUpdate(),但我出错了,无法修复。我看到spring-data-jpa docs,但没有找到解决方案。关于动态表名,我想备份db表或拍照数据你提醒我,我可以用另一种方式实现我的需求。
    • 好吧,如果没有看到错误,我无法完全判断出了什么问题。顺便说一句,我忘了告诉你,DDL 也应该使用@Modifying @Query(nativeQuery = true, value =...) 与常规存储库方法一起使用,而无需使用存储库碎片,但是你失去了动态提供表名的能力
    • 好吧,我再想想办法
    最近更新 更多