我使用的是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。
但是,当我插入新角色时,我会执行以下操作:
我可以成功保存,这很棒!!!!适合我。 并且在新的对象返回中,我可以清楚地看到新的roleId返回给我!!! 所有其他字段都是RoleEntity,就像说明那样。
但是,我个人想要的是完全填充RoleEntity的User和Award字段,就好像我在插入后完成了select一样。这甚至可能吗?
我更愿意不对用户进行选择并奖励表格以获取这些对象,然后将它们分配给此对象,但如果我必须这样做,那就没关系。
如果我需要提供更多信息,请告诉我。 感谢您提前提供任何帮助。
答案 0 :(得分:1)
尝试这种方法:
sess.save(role);
sess.flush(); //force the SQL INSERT
sess.refresh(role);
答案 1 :(得分:0)
这里有两件事。首先,您不应仅使用此ID创建具有已知ID的新实体。这种方法是一个等待发生的事故:具有此ID的实体已经存在,并且由于此重复密钥,您将遇到ConstraintViolationException
或NonUniqueObjectException
。
如果你想使用具有已知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可以做到这一点的唯一方法是使用Second Level Cache(L2C),但是根据你的问题我假设没有L2C。
即使你的@ManyToOne
关联是 eager-fetched ,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 docs以便更好地理解。如果你想在生产级别上使用Hibernate,你还应该阅读一本好的Hibernate书,如Java Persistence with Hibernate。
希望这会有所帮助。