【问题标题】:execute() stucks after using Hibernate methods使用 Hibernate 方法后执行()卡住
【发布时间】:2021-06-07 17:45:16
【问题描述】:

我有一个通过 JDBC (UserDaoJDBCImpl ()) 和 Hibernate (UserDaoHibernateImpl ()) 分别与 DB 交互的 DAO 实现。它们有用于创建 (createUsersTable ()) 和删除 (dropUsersTable ()) 表的方法,在这两种实现中都是通过 statement.execute () 方法完成的。通过 JDBC 实现运行顺利。问题如下:如果在使用 Hibernate 工具(会话、事务)的方法后创建或删除表,则 statement.executeUpdate() 将挂在其中。我认为这是由于使用 Hibernate 后资源没有关闭,但我不明白究竟是什么。以下是创建、删除的方法,以及 kaput 所遵循的方法之一。还有link to the github

public void createUsersTable() {
    try (Statement statement = Util.connectDB().createStatement()) {
        // нужен ли здесь автоинкремент у айди, если он прописан в аннотации?
        statement.execute("CREATE TABLE IF NOT EXISTS User" +
                "(id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT," +
                "name VARCHAR(50) NOT NULL," +
                "lastName VARCHAR(50)," +
                "age TINYINT(3))");
    } catch (SQLException e) {
        System.out.println("Create table exception");
        e.printStackTrace();
    }
}

public void dropUsersTable() {
    try (Statement statement = Util.connectDB().createStatement()) {
        statement.execute("DROP TABLE IF EXISTS User");
    } catch (SQLException e) {
        System.out.println("Drop table exception");
        e.printStackTrace();
    }
}

public void saveUser(String name, String lastName, byte age) {
        Session session = Util.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();
        session.save(new User(name, lastName, age));
        session.getTransaction().commit();
        session.close();
    }

还有会话工厂:

private static final String URL = "jdbc:mysql://localhost:3306/usersdb?useSSL=false";
private static final String USER = "root";
private static final String PASSWORD = "root";

private static SessionFactory sessionFactory;

public static SessionFactory getSessionFactory() {
    if(sessionFactory == null) {
        try {
            Properties properties = new Properties();
            properties.setProperty("hibernate.connection.driver_class", "com.mysql.cj.jdbc.Driver");
            properties.setProperty("hibernate.connection.url", URL);
            properties.setProperty("hibernate.connection.username", USER);
            properties.setProperty("hibernate.connection.password", PASSWORD);
            properties.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");

            Configuration configuration = new Configuration()
                    .addProperties(properties).addAnnotatedClass(User.class);
            StandardServiceRegistryBuilder builder =
                    new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
            sessionFactory = configuration.buildSessionFactory(builder.build());

        } catch (Exception e) {
            System.out.println("Creating sessionFactory exception");
            // e.printStackTrace();
        }
    }
    return sessionFactory;
}

在卡住的方法之前成功通过方法的日志:

мар. 09, 2021 10:26:17 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.0.Final}
мар. 09, 2021 10:26:17 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
мар. 09, 2021 10:26:17 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
мар. 09, 2021 10:26:17 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
мар. 09, 2021 10:26:17 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
мар. 09, 2021 10:26:17 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.cj.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/usersdb?useSSL=false]
мар. 09, 2021 10:26:17 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {password=****, user=root}
мар. 09, 2021 10:26:17 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
мар. 09, 2021 10:26:17 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
мар. 09, 2021 10:26:17 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
мар. 09, 2021 10:26:18 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory

【问题讨论】:

  • 如果在 main 方法中不添加任何 DB 调用会发生什么
  • @Acewin 所以一切正常

标签: java hibernate jdbc


【解决方案1】:

我查看了您的Main.java 课程,您似乎在启动应用程序时使用了createUsersTable()dropUsersTable()

使用 JDBC,您确实必须处理所有这些事情,例如表的创建和删除(如果需要)。

Hibernate 是另一回事,您不必手动删除或创建表。如果您确实需要这样做,有一种更有效的方法可以做到这一点,只需在您的 getSessionFactory() 方法中添加以下属性:

properties.setProperty("hibernate.hbm2ddl.auto", "create");

这样,当创建 SessionFactory 时,数据库表将被删除(如果存在)并重新创建。

您可以查看User guide 以了解该属性的可能值。

我不知道您使用的 Hibernate 版本,但这些值也适用于旧版本。

【讨论】:

  • 补充 Marco 的观点,即休眠查询引擎不允许在 ddl 上执行。创建和删除表是 ddl
  • 确实,这就是为什么在 JDBC 中有效而在 Hibernate 中无效的原因。 @Enesan 说它卡住了,但在我看来,很难预测内部会发生什么。
  • 谢谢你的回答,马可。这对我来说真的很有用。我正在使用休眠 5。但在我的任务中说“使用 SQL 在 UserDaoHibernateImpl 的方法中实现添加和删除表”。我认为这意味着我必须为此使用 JDBC 工具。一个人告诉我,我的 SessionFactory 有问题。但我尝试了不同的变体,没有任何其他结果
  • 是的,在 Hibernate 中无法执行 DDL,因此您必须使用 JDBC。
【解决方案2】:

通过将事务打开/关闭添加到 getAllUsers() 方法来解决问题。我真的没想到这个问题会出现在那里。无论如何,编译器都没有触及这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 2021-05-13
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    相关资源
    最近更新 更多