gpt4 book ai didi

java - OneToOne Find 上的 JPA/Hibernate 双选

转载 作者:行者123 更新时间:2023-12-02 12:13:57 28 4
gpt4 key购买 nike

在学习 JPA/Hibernate 时,我偶然发现了一些意想不到的事情。我对数据库进行了不必要的双重选择查询(请参见按钮)。我有一个简单的 OneToOne 设置。

这是我的联系人实体:

@Entity
@Table(name = "contact")
public class Contact {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "contact_id", nullable = false, insertable = false, updatable = false)
private Long id;

@Column(name = "name", nullable = false)
private String name;

@OneToOne
@JoinColumn(name="fk_address_id", referencedColumnName="address_id")
private Address address;

public Contact(String name, Address address) {
this.name = name;
this.address = address;
}

// getters/setters

}

我的地址实体:

@Entity
@Table(name = "address")
public class Address {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "address_id", nullable = false, insertable = false, updatable = false)
private Long id;

@Column(name = "location", nullable = false)
private String location;

@OneToOne(mappedBy = "address")
private Contact contact;

public Address(String location) {
this.location = location;
}

// getters/setters

}

这就是我运行代码的方式:

  private EntityManager em;

@Before
public void setup() {
em = EntityManagerFactoryCreator.getEntityManagerFactory().createEntityManager();
}

@Test
public void createContactWithAddress() {
Address address = new Address("Made");
Contact contact = new Contact("Jan", address);

em.getTransaction().begin();
em.persist(address);
em.persist(contact);
em.getTransaction().commit();

em.close();
em = EntityManagerFactoryCreator.getEntityManagerFactory().createEntityManager();

Contact managedContact = em.find(Contact.class, 1L);
}

}

这可能是一些愚蠢的事情,但是是什么导致了双重选择?

Hibernate: 

drop table address if exists
Hibernate:

drop table book if exists
Hibernate:

drop table contact if exists
Hibernate:

create table address (
address_id bigint generated by default as identity,
location varchar(255) not null,
primary key (address_id)
)
Hibernate:

create table book (
book_id bigint generated by default as identity,
category varchar(255),
release_date date,
summary varchar(255),
title varchar(255) not null,
primary key (book_id)
)

Hibernate:

create table contact (
contact_id bigint generated by default as identity,
name varchar(255) not null,
address_address_id bigint,
primary key (contact_id)
)
Hibernate:

alter table book
add constraint UK_g0286ag1dlt4473st1ugemd0m unique (title)
Hibernate:

alter table contact
add constraint FKrc0ixa9b11b9tv3hyq0iwvdpt
foreign key (address_address_id)
references address
Hibernate:
insert
into
address
(address_id, location)
values
(null, ?)
TRACE o.h.t.d.s.BasicBinder [main]: binding parameter [1] as [VARCHAR] - [Made]
Hibernate:
insert
into
contact
(contact_id, address_address_id, name)
values
(null, ?, ?)
TRACE o.h.t.d.s.BasicBinder [main]: binding parameter [1] as [BIGINT] - [1]
TRACE o.h.t.d.s.BasicBinder [main]: binding parameter [2] as [VARCHAR] - [Jan]
Hibernate:
select
contact0_.contact_id as contact_1_2_0_,
contact0_.address_address_id as address_3_2_0_,
contact0_.name as name2_2_0_,
address1_.address_id as address_1_0_1_,
address1_.location as location2_0_1_
from
contact contact0_
left outer join
address address1_
on contact0_.address_address_id=address1_.address_id
where
contact0_.contact_id=?
TRACE o.h.t.d.s.BasicBinder [main]: binding parameter [1] as [BIGINT] - [1]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([address_1_0_1_] : [BIGINT]) - [1]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([address_3_2_0_] : [BIGINT]) - [1]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([name2_2_0_] : [VARCHAR]) - [Jan]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([location2_0_1_] : [VARCHAR]) - [Made]
Hibernate:
select
contact0_.contact_id as contact_1_2_1_,
contact0_.address_address_id as address_3_2_1_,
contact0_.name as name2_2_1_,
address1_.address_id as address_1_0_0_,
address1_.location as location2_0_0_
from
contact contact0_
left outer join
address address1_
on contact0_.address_address_id=address1_.address_id
where
contact0_.address_address_id=?
TRACE o.h.t.d.s.BasicBinder [main]: binding parameter [1] as [BIGINT] - [1]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([address_1_0_0_] : [BIGINT]) - [1]
TRACE o.h.t.d.s.BasicExtractor [main]: extracted value ([contact_1_2_1_] : [BIGINT]) - [1]

注意:我的 EntityManagerFactoryCreator 是一个调用的单例Persistence.createEntityManagerFactory("nl.infosupport.javaminor.week4.jpa.h2");

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">

<persistence-unit name="nl.infosupport.javaminor.week4.jpa.h2">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<properties>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value="sa"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:~/Documents/InfoSupport-Minor/h2_embedded_db/test"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>

<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>

</persistence>

最佳答案

在这种情况下以及您拥有的表配置中,这是正常行为。如果您只想进行一项选择,则需要使用自定义查询来连接子表。例如,使用 HQL 它看起来像这样:

    public Contact find(Long id) {
TypedQuery<Contact> query = em.createQuery(
"SELECT c FROM Contact c join fetch c.address WHERE c.id = :id", Contact.class);
return query
.setParameter("id", id)
.getSingleResult();
}

代码不一定能工作,我没有调试它,但它显示了原理。

已更新

<小时/>

或者您可以尝试像这样注释该字段

@Fetch(FetchMode.JOIN)
private Address address;

And then it will fire just one query .

关于java - OneToOne Find 上的 JPA/Hibernate 双选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46330008/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com