Insert with Hibernate with child objects does not return full object

我只是一个虾纸丫 提交于 2020-01-24 00:32:29

问题


I am using Spring 3.2 and hibernate-core 4.1.4 and hibernate-jpa-2.0.1. The application resource file has all the correct objects.

I have a child object RoleEntity, and it has two parents: User and Award, so the userId and the awardId are foreign-keys that already exist, and MUST exist for the role entity to be created.

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
}

My DAO insert looks very simple:

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

I have unit tested this code, and I can confirm that when I select an existing roleId, I can fully get back the loaded object, with User and Award fully populated.

However, when I insert new role, I do the following:

  1. set roleId to 0, and the role description ...
  2. create a userEntity and set the id only, this id already exists and is not new
  3. create a awardEntity and set the id only, this id already exists and is not new

I can successfully do a save and this is great!!!! Works for me. And in the new object return, I can clearly see the new roleId is returned to me!!! All the other fields to RoleEntity, like the description, that is there.

But, what I ALSO want is for the User and Award fields of the RoleEntity to be fully populated as if I had done a select after the insert. Is this even possible?

I would prefer to not do a select to the user and award tables to get those objects and then assign them to this object, but if I have to do that, then that's fine.

If I need to provide any more information, please let me know. Thanks for any help in advance.


回答1:


Try this approach:

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




回答2:


Two things here. First of all you shouldn't create new entities with known IDs just to use this ID. This approach is an accident waiting to happen: an entity with this ID already exists and you will run into a ConstraintViolationException or NonUniqueObjectException because of this duplicate key.

With Hibernate you can use proxies if you want to use an entity with a known ID but you do not want to select the full entity from the database.

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

This will not hit the database to select the entities but a proxy (which wraps the known id) will be returned. Within the same session you can than use the proxy like the full entity and create the new RoleEntity

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

The second thing is: how should Hibernate know the non-id properties of your entities without hitting the database!? The only way Hibernate could do this is using the Second Level Cache (L2C), but from your question I assume that there is no L2C in place.

Even though your @ManyToOne associations are eager-fetched Hibernate must hit the database to populate the according entities. So you may use the approach from @Bogdan's answer and re-load the role and associated user and award entities after the insert

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

but this will have no performance benefit over selecting the according entities first in order to assign them to the new role

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

This will hit the database immediately and populate your entities (or return null if no row with the given ID exists).

Note that when you are using proxies you can populate your entities on-demand within the same session. As soon as a non-id property is accessed the according entity is selected from the database.

That said, I recommend to take a look at the Hibernate docs for a better understanding. If you want to work with Hibernate on a production level you should also read a good Hibernate book like Java Persistence with Hibernate.

Hope this helps.



来源:https://stackoverflow.com/questions/14655142/insert-with-hibernate-with-child-objects-does-not-return-full-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!