嗯,这个标题有很多问题,但没有一个有正确的答案,或者它们与我的不完全相同。
我有两个实体:
人:
@Entity
@Table(name = "Person")
@Inheritance(strategy = InheritanceType.JOINED)
@Access(AccessType.FIELD)
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(name = "firstname")
private String firstName;
@Column(name = "lastname", length = 100, nullable = false, unique = false)
private String lastName;
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.MERGE, mappedBy="owner")
private Set<Car> cars;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<Car> getCars() {
return cars;
}
public void setCars(Set<Car> cars) {
this.cars = cars;
}
@Override
public String toString() {
return String.format("(%d, %s, %s)",id, firstName, lastName);
}
}
和汽车:
@Entity
@Table(name = "Car")
@Inheritance(strategy = InheritanceType.JOINED)
@Access(AccessType.FIELD)
public class Car {
@Id
@GeneratedValue
private Long id;
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.MERGE)
@JoinColumn(name="id_person", columnDefinition="BIGINT")
private Person owner;
@Column(name="name")
private String name;
@Column(name="model")
private String model;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return String.format("(%d, %s, %s, %s)", id, name, model, owner);
}
}
此外,我在id_person列上的Person和Car表之间的Mysql数据库中定义了外键约束
我的persistence.xml文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- Configuring JDBC properties -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/hibernatedb" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="DA_PASSWORD" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<!-- Hibernate properties -->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<!-- Configuring Connection Pool -->
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="500" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="2000" />
</properties>
</persistence-unit>
</persistence>
在我的代码中,我尝试使用Criteria查询选择Cars如下:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> q = cb.createQuery(Car.class);
Root<Car> root = q.from(Car.class);
q.select(root);
当我得到结果并打印出来时
TypedQuery<Car> typedQuery = entityManager.createQuery(q);
List<Car> cars = typedQuery.getResultList();
log.info("*****************************{}", cars);
令我惊讶的是,它打印出来:
*****************************[(1, Hiundai, 2016, (1, Homer1530962140, Simpson)), (2, Benz, 2016, (1, Homer1530962140, Simpson)), (3, Benz,
2017, (2, Homer12935192, Simpson))]
这意味着对于每个汽车物品,业主也急切地被抓住了!
以下是数据库查询日志:
2017-02-17T14:02:58.324926Z 391 Query /* mysql-connector-java-5.1.13 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment
2017-02-17T14:02:58.325405Z 391 Query SHOW COLLATION
2017-02-17T14:02:58.335552Z 391 Query SET NAMES latin1
2017-02-17T14:02:58.335772Z 391 Query SET character_set_results = NULL
2017-02-17T14:02:58.336160Z 391 Query SET autocommit=1
2017-02-17T14:02:58.336349Z 391 Query SET autocommit=0
2017-02-17T14:02:58.720821Z 391 Query SHOW FULL TABLES FROM `hibernatedb` LIKE 'Car'
2017-02-17T14:02:58.724527Z 391 Query SHOW FULL TABLES FROM `hibernatedb` LIKE 'Car'
2017-02-17T14:02:58.725337Z 391 Query SHOW FULL COLUMNS FROM `Car` FROM `hibernatedb` LIKE '%'
2017-02-17T14:02:58.729899Z 391 Query SHOW FULL TABLES FROM `hibernatedb` LIKE 'Person'
2017-02-17T14:02:58.730468Z 391 Query SHOW FULL TABLES FROM `hibernatedb` LIKE 'Person'
2017-02-17T14:02:58.730887Z 391 Query SHOW FULL COLUMNS FROM `Person` FROM `hibernatedb` LIKE '%'
2017-02-17T14:02:59.022835Z 391 Query select car0_.id as id1_0_, car0_.model as model2_0_, car0_.name as name3_0_, car0_.id_person as id_perso4_0_ from Car car0_
2017-02-17T14:02:59.041016Z 391 Query SHOW WARNINGS
2017-02-17T14:02:59.045266Z 391 Query select person0_.id as id1_1_0_, person0_.firstname as firstnam2_1_0_, person0_.lastname as lastname3_1_0_ from Person person0_ where person0_.i
d=1
2017-02-17T14:02:59.059184Z 391 Query SHOW WARNINGS
2017-02-17T14:02:59.064163Z 391 Query select person0_.id as id1_1_0_, person0_.firstname as firstnam2_1_0_, person0_.lastname as lastname3_1_0_ from Person person0_ where person0_.i
d=2
2017-02-17T14:02:59.065827Z 391 Query SHOW WARNINGS
2017-02-17T14:02:59.070262Z 391 Query rollback
2017-02-17T14:02:59.070468Z 391 Quit
很明显,我发出了一个单独的查询来获取Person信息,而我似乎并没有在我的代码中提出这样的问题。
为什么会这样?
答案 0 :(得分:2)
您在将汽车转换为字符串时请求了所有者信息。
@Override
public String toString() {
return String.format("(%d, %s, %s, %s)", id, name, model, owner);
}
此时,必须检索所有者以执行toString()。
答案 1 :(得分:2)
string master_ConnectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;Database=Master;Integrated Security=True;Connect Timeout=30;";
using (SqlConnection restoreConn = new SqlConnection())
{
restoreConn.ConnectionString = master_ConnectionString;
restoreConn.Open();
using (SqlCommand restoredb_executioncomm = new SqlCommand())
{
restoredb_executioncomm.Connection = restoreConn;
restoredb_executioncomm.CommandText = @"RESTORE DATABASE yourdbname FROM DISK='c:\yourdbname.bak'";
restoredb_executioncomm.ExecuteNonQuery();
}
restoreConn.Close();
}
执行此操作时:
log.info("*****************************{}", cars);
toString()
都会调用toString()
car类的Car
方法调用toString
类的toString()
方法。这就是&#34;魔术&#34;发生。事实证明,Hibernate使用生成的代理类来为一些关联启用延迟加载(一对一,多对一)。换句话说,Hibernate通过引用扩展Person
类的代理类来初始化字段Car.owner
。此代理类包含处理延迟加载的其他逻辑。