Hibernate:为什么不调用完整的构造函数?

时间:2014-07-17 15:52:12

标签: java hibernate

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

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

是否有一个技巧或任何会使Hibernate使用完整构造函数的东西?这也适用于实体的所有儿童。我遇到了一个问题,我的query.list()运行缓慢,想要让它工作,看它是否会加快速度。

谢谢!

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

3 个答案:

答案 0 :(得分:3)

通过Hibernate实例化对象有三种策略(我知道)。

标准方法

HQL或标准查询(如select from cat)将创建POJO(此处为Cat - 或子类的实例),Hibernate将通过调用no-arg构造函数来实现。来自文档:

  

所有持久化类必须具有默认构造函数(可以是非公共的),以便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对象上指定如何将结果转换为对象。使用AliasToBeanConstructorResultTransformer,其中java.lang.Constructor作为参数,您可以选择被调用的构造函数。 (默认情况下,每个条件都有ResultTransformer RootEntityResultTransformer)。

答案 1 :(得分:1)

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

以下是其他一些问题:

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比数据库设置本身更简单,更孤立。但是,请记住,查询优化器会在第一次查询运行后启动。

答案 2 :(得分:0)

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

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

检查here