Hibernate菜鸟获取联接问题

我有两个类,Test2和Test3。Test2具有属性test3,它是Test3的实例。换句话说,我有一个单向的OneToOne关联,其中test2引用了test3。

当我从数据库中选择Test2时,可以看到正在进行单独的选择以获取关联的test3类的详细信息。这是著名的1 + N选择问题。

为了解决此问题,使其仅使用一个选择,我尝试使用fetch = join批注,我将其理解为@Fetch(FetchMode.JOIN)

但是,将获取设置为加入时,我仍然看到单独的选择。这是我设置的相关部分。

hibernate.cfg.xml:

<property name="max_fetch_depth">2</property>

测试2:

public class Test2 {

@OneToOne (cascade=CascadeType.ALL , fetch=FetchType.EAGER)

@JoinColumn (name="test3_id")

@Fetch(FetchMode.JOIN)

public Test3 getTest3() {

return test3;

}

注意我出于绝望而将FetchType设置为EAGER,尽管对于OneToOne映射它还是默认为EAGER,但这没有什么区别。

谢谢你的帮助!

编辑:我已经完全放弃尝试使用FetchMode.JOIN-有人可以确认他们已经使用它了,即产生一个左外部联接吗?在文档中,我看到“通常,映射文档不用于自定义获取。相反,我们保留默认行为,并使用HQL中的左连接获取来对特定事务覆盖它”

如果我改为进行左连接获取:

查询= session.createQuery(“从Test2 t2左联接获取t2.test3”);

那么我确实得到了想要的结果-即查询中的左外部联接。

编辑数字2:

伙计们,非常感谢您的答复。现在,我想深入了解这一点。我通常会发现,当我进行调查时,最终会比我想像的多得多。

我已经学到的一件事-我在旧版本的Hibernate上运行,因为我没有意识到Maven存储库已经过时。现在,我也已经连接到jboss存储库,并且拥有最新版本的hibernate和hibernate批注-两种情况下均为3.5.1-Final。

我已经设置了一个尽可能小的简化的测试用例-我仍然在3.5.1-Final中看到问题,因为我99%肯定这只是我没有设置的愚蠢行为没错,特别是罗斯,因为您可以使用它(感谢您抽出宝贵的时间尝试一下)

所以我有这些课(这次是全文)

A级

package com.play.hibernate2;

import javax.persistence.CascadeType;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.OneToOne;

import org.hibernate.annotations.Fetch;

import org.hibernate.annotations.FetchMode;

@Entity

public class A {

private Integer id;

private B b;

public A() {

super();

}

@Id

@GeneratedValue

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

@OneToOne (cascade=CascadeType.ALL)

@Fetch(FetchMode.JOIN)

public B getB() {

return b;

}

public void setB(B b) {

this.b = b;

}

}

B级

package com.play.hibernate2;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

@Entity

public class B {

private Integer id;

public B() {

super();

}

@Id

@GeneratedValue

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

}

我的整个hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- <property name="connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property> -->

<property name="connection.url">jdbc:mysql://localhost:3306/play</property>

<property name="connection.username">play</property>

<property name="connection.password">play</property>

<!-- JDBC connection pool (use the built-in) -->

<property name="connection.pool_size">1</property>

<!-- SQL dialect -->

<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- Enable Hibernate's automatic session context management -->

<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->

<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<property name="generate_statistics">true</property>

<!--

<property name="cache.use_structured_entries">true</property>

<property name="cache.use_query_cache">true</property>

-->

<property name="format_sql">true</property>

<property name="use_sql_comments">true</property>

<!-- I think this may fix my individual requests for OneToOne problem -->

<property name="max_fetch_depth">2</property>

<!-- <property name="default_batch_fetch_size">10</property> -->

</session-factory>

</hibernate-configuration>

测试班

package com.play.hibernate2;

import java.util.List;

import java.util.Map;

import org.hibernate.FlushMode;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

import org.hibernate.tool.hbm2ddl.SchemaExport;

public class RunTests4 {

private SessionFactory sessionFactory;

public static void main(String[] args){

RunTests4 d = new RunTests4();

d.run3();

}

public void run3(){

Session session = getSession();

session.beginTransaction();

createEntities(session);

session.getTransaction().commit();

System.out.println("NOW WITH A NEW TRANSACTION");

session = getSession();

session.beginTransaction();

Query query = session.createQuery("from A");

List results = query.list();

for (int i=0; i<results.size(); i++){

System.out.println("Row "+i+" was:");

A a = (A)results.get(i);

System.out.println("Result "+i);

System.out.println(a.toString());

}

session.getTransaction().commit();

}

public void createEntities(Session session){

for (int i=0; i<2; i++){

A a = new A();

B b = new B();

a.setB(b);

session.save(a);

}

}

public Session getSession(){

if (sessionFactory == null){

AnnotationConfiguration config = new AnnotationConfiguration();

config.addAnnotatedClass(A.class);

config.addAnnotatedClass(B.class);

config.configure();

new SchemaExport(config).create(true,true);

sessionFactory = config.buildSessionFactory();

}

Session session = sessionFactory.getCurrentSession();

return session;

}

}

最后,日志输出显示了额外的选择,以取回相关的类

2 [main] INFO org.hibernate.cfg.annotations.Version - Hibernate Annotations 3.5.1-Final

23 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.5.1-Final

28 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found

32 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist

37 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling

160 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.2.0.Final

176 [main] INFO org.hibernate.cfg.Configuration - configuring from resource: /hibernate.cfg.xml

176 [main] INFO org.hibernate.cfg.Configuration - Configuration resource: /hibernate.cfg.xml

313 [main] INFO org.hibernate.cfg.Configuration - Configured SessionFactory: null

338 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.MySQLDialect

462 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.Test2

545 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.Test2 on table Test2

649 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.Test3

650 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.Test3 on table Test3

651 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.A

651 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.A on table A

653 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.play.hibernate2.B

653 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.play.hibernate2.B on table B

678 [main] INFO org.hibernate.cfg.AnnotationConfiguration - Hibernate Validator not found: ignoring

687 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - Running hbm2ddl schema export

688 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - exporting generated schema to database

691 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!)

691 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 1

698 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: false

711 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/play

711 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=play, password=****}

alter table A

drop

foreign key FK412E010759

alter table Test2

drop

foreign key FK4CF5DC04B7E1B79

drop table if exists A

drop table if exists B

drop table if exists Test2

drop table if exists Test3

create table A (

id integer not null auto_increment,

b_id integer,

primary key (id)

)

create table B (

id integer not null auto_increment,

primary key (id)

)

create table Test2 (

id integer not null auto_increment,

name varchar(255),

value integer not null,

test3_id integer,

primary key (id)

)

create table Test3 (

id integer not null auto_increment,

name varchar(255),

value integer not null,

primary key (id)

)

alter table A

add index FK412E010759 (b_id),

add constraint FK412E010759

foreign key (b_id)

references B (id)

alter table Test2

add index FK4CF5DC04B7E1B79 (test3_id),

add constraint FK4CF5DC04B7E1B79

foreign key (test3_id)

references Test3 (id)

2562 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete

2564 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:mysql://localhost:3306/play

2571 [main] INFO org.hibernate.cfg.search.HibernateSearchEventListenerRegister - Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.

2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!)

2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - Hibernate connection pool size: 1

2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - autocommit mode: false

2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/play

2575 [main] INFO org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=play, password=****}

2622 [main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: MySQL, version: 5.1.30

2622 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.9 ( Revision: ${svn.Revision} )

2633 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.MySQLDialect

2635 [main] INFO org.hibernate.engine.jdbc.JdbcSupportLoader - Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4

2636 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Using default transaction strategy (direct JDBC transactions)

2638 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)

2638 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic flush during beforeCompletion(): disabled

2638 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic session close at end of transaction: disabled

2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch size: 15

2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC batch updates for versioned data: disabled

2638 [main] INFO org.hibernate.cfg.SettingsFactory - Scrollable result sets: enabled

2638 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC3 getGeneratedKeys(): enabled

2638 [main] INFO org.hibernate.cfg.SettingsFactory - Connection release mode: auto

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Maximum outer join fetch depth: 2

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Default batch fetch size: 1

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Generate SQL with comments: enabled

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL updates by primary key: disabled

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL inserts for batching: disabled

2639 [main] INFO org.hibernate.cfg.SettingsFactory - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory

2641 [main] INFO org.hibernate.hql.ast.ASTQueryTranslatorFactory - Using ASTQueryTranslatorFactory

2641 [main] INFO org.hibernate.cfg.SettingsFactory - Query language substitutions: {}

2641 [main] INFO org.hibernate.cfg.SettingsFactory - JPA-QL strict compliance: disabled

2641 [main] INFO org.hibernate.cfg.SettingsFactory - Second-level cache: enabled

2641 [main] INFO org.hibernate.cfg.SettingsFactory - Query cache: disabled

2644 [main] INFO org.hibernate.cfg.SettingsFactory - Cache region factory : org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge

2644 [main] INFO org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge - Cache provider: org.hibernate.cache.NoCacheProvider

2644 [main] INFO org.hibernate.cfg.SettingsFactory - Optimize cache for minimal puts: disabled

2644 [main] INFO org.hibernate.cfg.SettingsFactory - Structured second-level cache entries: disabled

2648 [main] INFO org.hibernate.cfg.SettingsFactory - Echoing all SQL to stdout

2648 [main] INFO org.hibernate.cfg.SettingsFactory - Statistics: enabled

2649 [main] INFO org.hibernate.cfg.SettingsFactory - Deleted entity synthetic identifier rollback: disabled

2649 [main] INFO org.hibernate.cfg.SettingsFactory - Default entity-mode: pojo

2649 [main] INFO org.hibernate.cfg.SettingsFactory - Named query checking : enabled

2649 [main] INFO org.hibernate.cfg.SettingsFactory - Check Nullability in Core (should be disabled when Bean Validation is on): enabled

2697 [main] INFO org.hibernate.impl.SessionFactoryImpl - building session factory

2796 [Finalizer] INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:mysql://localhost:3306/play

2929 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured

Hibernate:

/* insert com.play.hibernate2.B

*/ insert

into

B

values

( )

Hibernate:

/* insert com.play.hibernate2.A

*/ insert

into

A

(b_id)

values

(?)

Hibernate:

/* insert com.play.hibernate2.B

*/ insert

into

B

values

( )

Hibernate:

/* insert com.play.hibernate2.A

*/ insert

into

A

(b_id)

values

(?)

NOW WITH A NEW TRANSACTION

Hibernate:

/*

from

A */ select

a0_.id as id2_,

a0_.b_id as b2_2_

from

A a0_

Hibernate:

/* load com.play.hibernate2.B */ select

b0_.id as id3_0_

from

B b0_

where

b0_.id=?

Hibernate:

/* load com.play.hibernate2.B */ select

b0_.id as id3_0_

from

B b0_

where

b0_.id=?

Row 0 was:

Result 0

com.play.hibernate2.A@351daa0e

Row 1 was:

Result 1

com.play.hibernate2.A@2e879860

编辑数字3:

如果我按罗斯的方式进行操作,那么就会产生左外连接。如果我使用列表进行操作,则会发出单独的选择。这是相关的代码。仅更改此设置即可重现行为上的差异:

    /* generates the left outer join

A a = (A)session.load(A.class,1);

System.out.println(a.getId()+" = "+a.getB().getName());

*/

// Creates separate selects for each object b associated with each a

Query query = session.createQuery("from A");

List results = query.list();

A a = (A)results.get(0);

System.out.println(a.getId()+" = "+a.getB().getName());

我猜它可能被称为“

bug”。正如我之前提到的,在文档中,他们说在HQL中而不是在映射中指定获取模式是“正常的”,我想这可能意味着HQL方式会占用更多的人流量。 。?

(通过向A和B添加一个额外的“名称”字段的方式,否则hibernate优化了检索,因为它可以仅从A上的外键获取所有B)

回答:

当我从数据库中选择Test2时,可以看到正在进行单独的选择以获取关联的test3类的详细信息。

我对另一个答案的代码非常感兴趣,因为这也是我在测试所显示的代码时看到的内容,它为a生成两个选择from Test2

我正在使用以下依赖项:

  • org.hibernate:hibernate-entitymanager:jar:3.4.0.GA:compile
  • org.hibernate:ejb3-persistence:jar:1.0.2.GA:compile
  • org.hibernate:hibernate-commons-annotations:jar:3.1.0.GA:compile
  • org.hibernate:hibernate-annotations:jar:3.4.0.GA:compile
  • org.hibernate:hibernate-core:jar:3.3.0.SP1:编译

我出于绝望而将FetchType设置为EAGER,尽管对于OneToOne映射无论如何它都默认为EAGER,但没有任何区别。

如果您使用Hibernate批注,则不会产生任何影响,因为Hibernate批注会覆盖EJB3的获取选项。见2.4.5.1。懒惰的选项和获取模式。

以上是 Hibernate菜鸟获取联接问题 的全部内容, 来源链接: utcz.com/qa/398290.html

回到顶部