【问题标题】:Hibernate OneToOne mapping executes select statement before insert; not sure whyHibernate OneToOne 映射在插入前执行 select 语句;不知道为什么
【发布时间】:2011-03-06 02:51:05
【问题描述】:

我在我的实体中配置了一个简单的 OneToOne 映射,但是当我持久化对象时,我看到 Hibernate 在插入之前正在执行“Select”语句,我不知道为什么。

@Entity 
@Table( name = "USER" )
public class NewUser {

   @OneToOne
   @JoinColumn(name="user_status_type_id", nullable=false)
   private UserStatusType userStatusType;

UserStatusType 只是一个只读查找表,因此当我保存 User 时,该表中没有任何内容。

User u = new User();
u.setUserStatusType( new UserStatusType(101));
session.persis(u);

但是当我持久化 User 对象时,Hibernate 的输出如下所示:

Hibernate: select userstatus_.user_status_type_id, userstatus_.user_status_name as user2_3_ from USER_STATUS_TYPE userstatus_ where userstatus_.user_status_type_id=?
Hibernate: insert into USER (created, first_name, last_name, password, user_name, user_status_type_id) values (?, ?, ?, ?, ?, ?)

我不知道这对于 Hibernate 是否正常。我想既然这是一个“持久”操作,我只会看到一个 Insert 语句;不确定 Select 的用途。

映射不正确吗?

【问题讨论】:

  • 如何持久化以及持久化时userStatusType引用了哪个对象?
  • 我在原帖中更新了更多细节

标签: hibernate


【解决方案1】:

好的,我可以从 Hibernate 论坛获得答案。为了防止SELECT出现在INSERT之前,如果您确定引用的行存在于数据库中,则使用Session.load()EntityManager.getReference()

User u = new User();
u.setUserStatusType( session.load(UserStatusType.class, new Long(id));
session.persist(u);

session.load() 方法最初不加载任何内容,它只是为对象创建一个代理并避免对数据库的访问。现在,如果你想在会话上下文中访问类中的成员(除了 id 字段),那么 Hibernate 将转到数据库。在我的例子中,我只需要 INSERT 的引用对象的主键,所以我避免了数据库命中。

【讨论】:

  • @user646584 很好的研究!您可以通过单击复选框来接受您自己的答案。
  • 我们能解释一下这种行为的原因(插入前选择)吗?
  • 我使用过 session.load 但它抛出了 ConstraintViolationException。在您的情况下,它正在抛出 UserStatusType 字段..
  • 这就是为什么我更喜欢普通的 jdbc - 清晰且易于维护。 Hibernate 掩盖了开发人员的意图,并产生了比它解决的问题更多的问题。
猜你喜欢
  • 1970-01-01
  • 2020-06-02
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多