Spring 使用Hibernate插入子对象不会返回完整对象
我正在使用Spring3.2、HibernateCore4.1.4和hibernate-jpa-2.0.1。应用程序资源文件具有所有正确的对象 我有一个子对象RoleEntity,它有两个父对象:User和Award,因此userId和awardId是已经存在的外键,并且必须存在才能创建角色实体Spring 使用Hibernate插入子对象不会返回完整对象,spring,hibernate,jpa,foreign-keys,parent-child,Spring,Hibernate,Jpa,Foreign Keys,Parent Child,我正在使用Spring3.2、HibernateCore4.1.4和hibernate-jpa-2.0.1。应用程序资源文件具有所有正确的对象 我有一个子对象RoleEntity,它有两个父对象:User和Award,因此userId和awardId是已经存在的外键,并且必须存在才能创建角色实体 public class RoleEntity implements Serializable { @Id @GeneratedValue(strategy = GenerationTy
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时,我可以完全恢复加载的对象,并且用户和奖励都已完全填充
但是,当我插入新角色时,我会执行以下操作:
sess.save(角色)
sess.flush()//强制SQL插入
更新(角色);
这里有两件事。首先,您不应该仅仅为了使用此ID而创建具有已知ID的新的实体。这种方法是一种等待发生的意外情况:具有此ID的实体已经存在,并且由于此重复键,您将遇到ConstraintViolationException
或UnonqueObjectException
使用Hibernate,如果您想使用具有已知ID的实体,但不想从数据库中选择完整实体,则可以使用代理
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属性,就会从数据库中选择相应的实体
UserEntity user = session.load(UserEntity.class, userId);
AwardEntity award = session.load(AwardEntity.class, awardId);
也就是说,为了更好地理解,我建议大家看看Hibernate。如果您想在生产级别上使用Hibernate,还应该阅读一本很好的Hibernate书籍,如
希望这有帮助