0

我正在使用 Spring 3.2 和 hibernate-core 4.1.4 和 hibernate-jpa-2.0.1。应用程序资源文件具有所有正确的对象。

我有一个子对象 RoleEntity,它有两个父对象:User 和 Award,因此 userId 和 AwardId 是已经存在的外键,并且必须存在才能创建角色实体。

public class RoleEntity implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "role_id")
    private long roleId;

    @Column(name = "role_description")
    private String roleDescription;

    @Column(name = "role_name")
    private String roleName;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    private UserEntity user;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "award_id")
    private AwardEntity award;

     ... getters/setters
     ... hash/equals/toString
}

我的 DAO 插入看起来很简单:

@Override
public RoleEntity saveRoleEntity(RoleEntity role)
{
     logger.debug("saveRoleEntity: role=" + role);
     return role;
}

我已经对该代码进行了单元测试,并且可以确认,当我选择现有的 roleId 时,我可以完全取回加载的对象,并且完全填充了 User 和 Award。

但是,当我插入新角色时,我会执行以下操作:

  1. 将 roleId 设置为 0,并将角色描述...
  2. 创建一个userEntity并只设置id,这个id已经存在并且不是新的
  3. 创建一个awardEntity并只设置id,这个id已经存在并且不是新的

我可以成功保存,这太棒了!!!!为我工作。而在新的对象返回中,我可以清楚的看到新的roleId返回给我了!!!RoleEntity 的所有其他字段,例如描述,都在那里。

但是,我还想要完全填充 RoleEntity 的 User 和 Award 字段,就好像我在插入后进行了选择一样。这甚至可能吗?

我宁愿不对用户和奖励表进行选择以获取这些对象,然后将它们分配给该对象,但如果我必须这样做,那很好。

如果我需要提供更多信息,请告诉我。感谢您提前提供任何帮助。

4

2 回答 2

1

试试这个方法:

sess.save(role);
sess.flush(); //force the SQL INSERT
sess.refresh(role);

于 2013-02-01T21:55:52.050 回答
0

这里有两件事。首先,您不应仅仅为了使用此 ID 而创建具有已知 ID 的新实体。这种方法是一个等待发生的意外:具有此 ID 的实体已经存在,您将遇到一个ConstraintViolationExceptionorNonUniqueObjectException因为这个重复的键。

如果您想使用具有已知 ID 的实体但不想从数据库中选择完整的实体,则可以使用 Hibernate 使用代理。

UserEntity user = session.load(UserEntity.class, userId);
AwardEntity award = session.load(AwardEntity.class, awardId);

这不会命中数据库来选择实体,但会返回一个代理(包装已知 id)。在同一个会话中,您可以像使用完整实体一样使用代理并创建新的RoleEntity

RoleEntity role = new RoleEntity();
role.setUser(user);
role.setAward(award);
session.save(role);

第二件事是:Hibernate 应该如何在不访问数据库的情况下知道实体的非 id 属性!?Hibernate 可以做到这一点的唯一方法是使用二级缓存(L2C),但根据您的问题,我假设没有 L2C。

即使您的@ManyToOne关联是预先获取的,Hibernate 也必须访问数据库以填充相应的实体。因此,您可以使用@Bogdan 回答中的方法,并在插入后重新加载角色以及关联的用户和奖励实体

session.save(role);
session.refresh(role);

但这与首先选择相应的实体以将它们分配给新角色相比没有性能优势

UserEntity user = session.get(UserEntity.class, userId);
AwardEntity award = session.get(AwardEntity.class, awardId);    

这将立即访问数据库并填充您的实体(如果不存在具有给定 ID 的行,则返回 null)。

请注意,当您使用代理时,您可以在同一会话中按需填充您的实体。一旦访问了非 id 属性,就会从数据库中选择相应的实体。

也就是说,我建议您查看 Hibernate文档以获得更好的理解。如果您想在生产级别上使用 Hibernate,您还应该阅读一本很好的 Hibernate 书籍,例如Java Persistence with Hibernate

希望这可以帮助。

于 2013-02-02T11:28:15.683 回答