【问题标题】:Hibernate: Why isn't the full constructor being called?Hibernate:为什么不调用完整的构造函数?
【发布时间】:2014-07-17 15:52:12
【问题描述】:

我为我们拥有的表填充了一个 HBM 文件。我认为创建了 Hibernate 将使用的 Java 实体。在实体中,我有一个空构造函数,然后是一个包含所有字段的完整构造函数。我也将它们按照与 HBM 文件中的顺序相同的顺序排列。

每次 Hibernate 使用 Entity 时,它总是调用空构造函数而不是完整构造函数。

有没有什么技巧可以让 Hibernate 使用完整的构造函数?这也发生在实体的所有孩子身上。我遇到了一个问题,我的 query.list() 运行缓慢,我想让它工作,看看它是否会加快速度。

谢谢!

注意: 我没有包含 HBM 和 Java 文件的内容,因为 (a) 它包含公司信息,并且 (b) 它相当大。剥离东西需要很长时间。如果给您带来不便,我很抱歉:(

【问题讨论】:

  • 如果投反对票,请告诉我原因,以便我调整问题。
  • 据我所知,Hibernate 不会调用“完整”构造函数。它将调用您的无参数构造函数,并根据您的设置方式进行字段或属性(getter/setter)调用。你检查过 Hibernate 文档吗? 2.2. The entity Java class
  • 我投了反对票(顺便说一句,我以前从未这样做过),因为如果你搜索这个主题,你会发现很多解释 hibernate 如何调用构造函数的命中。我将删除反对票(如果系统允许我),但似乎您在发布问题之前没有进行搜索。如果我错了,我道歉。但无论如何,hibernate 都会调用默认/无参数的构造函数。
  • 我确实进行了搜索。其中一篇文章(来自这里)提到他们创建了一个完整的构造函数并解决了这个问题。所以我继续尝试了它,但是对于我尝试的每一种方式,它都不会调用完整的构造函数而不是无参数的构造函数。

标签: java hibernate


【解决方案1】:

通过 Hibernate 实例化对象有 3 种策略(据我所知)。

标准方法

HQL 或 select from cat 之类的条件查询将创建 POJO(这里是 Cat 或子类的实例),Hibernate 将通过调用无参数构造函数来实现。来自文档:

所有持久类都必须有一个默认构造函数(可以是非公共的),以便 Hibernate 可以使用 java.lang.reflect.Constructor.newInstance() 实例化它们。建议至少在包可见性的情况下定义此构造函数,以便运行时代理生成正常工作。

使用 HQL 选择构造函数

可以通过 HQL 查询中特制的 select 语句引用特定的构造函数来调用。
例如。 select new com.example.Cat(cat.id, cat.name) from Cat 有效。如果您的请求定义正确,您还可以在您的选择中使用count() 等函数。这将在 Cat 上调用 2 个参数构造函数 - 虽然我不认为这会自动调整以找到另一个 Cat 的类以防多态。

您可以在文档中探索各种可能性(例如如何构建列表):http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-select

使用结果转换器

ResultTransformer 的概念允许您在Criteria 对象上指定如何将结果转换为对象。使用以java.lang.Constructor 作为参数的AliasToBeanConstructorResultTransformer,您可以选择要调用的构造函数。 (默认情况下,每个条件都有一个ResultTransformer,即RootEntityResultTransformer)。

【讨论】:

    【解决方案2】:

    您正在处理非常大的结果集吗?您使用的是什么存储库?我遇到过类似的问题,归结为休眠的数据库设置。

    还有一些其他问题需要检查:

    Simple hibernate query returning very slowly

    Hibernate queries slow down drastically after an entity is loaded in the session

    对于休眠,我发现您可以调整以下设置以提高性能。 :

            // update - Create if schema doesn't exists; update if column doesn't
        // exist
        // create - Empties the database before creating it
        // create-drop - Drops the database when the SessionFactory is closed
        config.setProperty("hibernate.hbm2ddl.auto", hbm2ddlMode);
        config.setProperty("hibernate.cache.use_query_cache", "true");
        config.setProperty("hibernate.cache.use_second_level_cache", "true");
        config.setProperty("hibernate.cache.region.factory_class",
            "org.hibernate.cache.ehcache.EhCacheRegionFactory");
        config.setProperty("hibernate.cache.provider_class",
            "org.hibernate.cache.EhCacheProvider");
        // config.setProperty("hibernate.cache.provider_class",
        // "org.hibernate.cache.NoCacheProvider");
        config.setProperty("hibernate.jdbc.fetch_size", "1000");
        config.setProperty("hibernate.jdbc.batch_size", "50"); //batches network calls in one
        config.setProperty("hibernate.jdbc.use_scrollable_resultset", "true");
    
        config.setProperty("hibernate.connection.provider_class",
            "org.hibernate.connection.C3P0ConnectionProvider");
        config.setProperty("hibernate.c3p0.acquire_increment", "1");
        config.setProperty("hibernate.c3p0.idle_test_period", "10");
        config.setProperty("hibernate.c3p0.min_size", "1");
        config.setProperty("hibernate.c3p0.max_size", "8");
        config.setProperty("hibernate.c3p0.timeout", "10");
        config.setProperty("javax.persistence.validation.mode", "none");
        config
            .setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
        config.setProperty("hibernate.show_sql", "false");
    

    请注意,这些特定设置可能不适合您的数据库,但您应该能够通过调整上述属性来提高性能。详细解释可以在doc site上找到。

    对于 sqlite,您必须调整一些额外的设置:

            config.setPageSize(4096);
        config.setCacheSize(-256);
    
        config.setSharedCache(true);
        config.setReadUncommited(true);
    
        //Be careful with these settings if needed for concurrency
        //***************************************************
        config.setLockingMode(LockingMode.NORMAL);
        config.setSynchronous(SynchronousMode.NORMAL);
        config.setJournalMode(JournalMode.WAL);
        config.setTempStore(TempStore.MEMORY);
        //***************************************************
    

    Postgres 更简单一些,并且更独立于数据库设置本身。但是,请记住,查询优化器会在第一次查询运行后启动。

    【讨论】:

      【解决方案3】:

      经过一番研究,我发现这很有用

      休眠实体必须定义无参数构造函数。 Hibernate 通过 reflection 使用Class.newInstance() 方法创建新的实体实例。 此方法需要无参数构造函数才能成功。如果实体不提供无参数构造函数,则会抛出 Hibernate 的 InstantiationException

      查看here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-25
        • 2017-04-09
        • 1970-01-01
        • 2011-09-07
        • 2021-02-18
        • 2014-01-14
        相关资源
        最近更新 更多