我有两个类,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
。
我正在使用以下依赖项:
我出于绝望而将FetchType设置为EAGER,尽管对于OneToOne映射无论如何它都默认为EAGER,但没有任何区别。
如果您使用Hibernate批注,则不会产生任何影响,因为Hibernate批注会覆盖EJB3的获取选项。见2.4.5.1。懒惰的选项和获取模式。
问题内容: 我有两个类,Test2和Test3。Test2具有属性test3,它是Test3的实例。换句话说,我有一个单向的OneToOne关联,其中test2引用了test3。 当我从数据库中选择Test2时,可以看到正在进行单独的选择以获取关联的test3类的详细信息。这是著名的1 + N选择问题。 为了解决此问题,使其仅使用一个选择,我尝试使用fetch = join批注,我将其理解为@Fe
30分钟 电话面 自我介绍 图中的最短路径算法 B+树,它的实现,有什么优势 JVM的内存结构 程序计数器的作用 红黑树及其应用 排序算法 抽象类和接口 乐观锁及其实现 偏向锁及其实现 框架有什么想学习的吗 数据库隔离级别他们的区别是什么 自旋锁 怎么实现RPC netty,NIO的实现 消息队列 CPU中多个核,多个线程共享内存怎么保证一致性 分布式如何保证一致性,如何实现 双亲委派机制 本地方
问实习经历 offer 拿没有?(没有实习转正) 实习期间有什么收获或者挑战? 实习期间有没有提前或者超时完成的任务? 更偏向于做基础中间件还是业务? 几个项目是学校老师指安排的课题吗? 2、八股文 tcp 三次握手的流程?两次握手的问题? tcp 拥塞控制的作用?拥塞控制有哪几种算法? 进程间通信有哪几种方式? 内存页面置换算法有哪几种方式? mysql 的第一范式和第二范式有什么区别? mys
约的1点半,实际面试开始2点,迟到半小时,KPI都懒得做样子了。😅😅😅 问了Springboot的自动装配过程,Error和Exception区别。 #秋招#
挺离谱的面试 #面经# 阿里-菜鸟部门 45min 状态:(基本oc,就差hr面了,说实话流程花的时间太长了,我刚签完美团了,明天hr面应该会拒掉) 没算法题(离谱在这了 自我介绍 什么是重力补偿(头一次有人问 把青训营开发项目源码调出来一下 介绍一下开发项目 讲讲你们为啥选go语言开发,为啥选Hertz这个框架 讲讲你负责的哪部分 说一下你的数据库设计 为什么用加密盐 把你整个登录注册逻辑
数字倒序输出 3个线程打印1-10 场景题,让理解加价购买和满减后,均摊到每个商品的价钱 缓存穿透,击穿,雪崩,怎么防止 rabbitMQ和rocket的区别 数据库的索引 数据库分库分表 数据库事务和锁 数据库唯一键 问了下项目 感觉都是一些讨论,具体的问题不多,一直问答不会为止