休眠持久化实体而不获取关联对象。仅凭身份证
Posted
技术标签:
【中文标题】休眠持久化实体而不获取关联对象。仅凭身份证【英文标题】:Hibernate persist entity without fetching association object. just by id 【发布时间】:2015-08-10 21:24:27 【问题描述】:我在 2 个实体之间有一个简单的关联:
public class Car
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
...
和
public class User
@Id
@GeneratedValue
@Column(name = "user_id")
private long userId;
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<Car> cars;
...
然后我从客户端获得一些用户 ID。例如,userId == 5; 为了与用户一起保存汽车,我需要执行以下操作:
User user = ... .findOne(userId);
Car car = new Car();
car.setUser(user);
... .save(car);
我的问题是:我可以在不获取用户的情况下保留汽车记录吗?
与使用本机 SQL 查询类似:只需在 Car 表中插入 userId,如 string(long)。 使用 2nd lvl 缓存会更快,但我认为我不需要做额外的动作。 我不想使用本机 Query 的主要原因是因为我的项目中的关联要困难得多,我需要 .save(car) 多次。此外,我不想手动控制查询执行的顺序。如果我使用 session.createSQLQuery("insert into .....values()") 将 Hibernate 的批量插入工作正常?
如果我错了,请纠正我。 提前致谢! 更新: 实际上映射类似于:
User 和 Car 之间存在 @ManyToMany 关联。但是交叉表也是一个被命名的实体,例如Passanger。所以接下来是映射:
public class User
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", targetEntity = Passenger.class)
private Set<Passenger> passengers;
跨实体
@IdClass(value = PassengerPK.class)
public class Passenger
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "car_id")
private Car car;
... other fields ...
汽车实体:
public class Car
@OneToMany(fetch = FetchType.LAZY, mappedBy = "car", targetEntity = Passenger.class, cascade = CascadeType.ALL)
private Set<Passenger> passengers;
还有代码:
List<User> users = ... .findInUserIds(userIds); // find user records where userId is IN userIds - collection with user Ids
Car car = new Car(); //initialization of car's fields is omitted
if (users != null)
car.setPassengers(new HashSet<>(users.size()));
users.forEach((user) -> car.getPassengers().add(new Passenger(user, car)));
... .save(car);
【问题讨论】:
您是否显示了确切的映射?从Car
到User
没有级联?
@DraganBozanovic,我已经更新了帖子。是的,有级联。
【参考方案1】:
“我可以在不获取用户的情况下保留汽车记录吗?”
是的,这是 Hibernate 代理的优点之一:
User user = entityManager.getReference(User.class, userId); // session.load() for native Session API
Car car = new Car();
car.setUser(user);
这里的重点是使用EntityManager.getReference:
获取一个实例,其状态可能会被延迟获取。
Hibernate 只会根据提供的 id 创建代理,而不从数据库中获取实体。
“如果我使用 session.createSQLQuery("insert into .....values()") 将 Hibernate 的批量插入工作正常吗?”
不,不会。查询会立即执行。
【讨论】:
你是对的。但如果你允许,我还有另一个问题。由于异常,我无法调用 .merge(car):分离实体传递给持久化?调用 saveOrUpdate() 不是一个选项,因为我需要 removeOrphan。 我建议您为此打开一个不同的问题,因为这似乎是一个不同的问题。在那里发布异常的整个堆栈跟踪,以便我们知道哪个实体被分离,等等。 我打开了新问题。请访问LINK 使用 eclipselink 您根本不需要获取参考。是在路上处理的。是否可以以相同的方式配置休眠? 这对于单个对象来说似乎没问题。是否有保存实体列表的选项。例如,如果我想用不同的用户保存汽车列表?【参考方案2】:如果有人在使用spring JPA,同样可以在Spring JPA中使用方法
getOne(userId)
【讨论】:
【参考方案3】:Hibernate 用户可以实现这个方法:
public <T extends Object> T getReferenceObject(Class<T> clazz, Serializable id)
return getCurrentSession().get(clazz, id);
然后像这样调用:
MyEntity myEntity = getRefererenceObject(MyEntity.class, 1);
您可以根据您的实体模型将 id 类型更改为 Integer 或 Long。 或者,如果您对所有实体都有一个基类,则 T 可以从您的 BaseEntity 继承。
【讨论】:
【参考方案4】:以下方法对我有用:
User user = new User();
user.setId(userId);
car.setUser(user);
【讨论】:
这是一个临时实体,它不会持久化。以上是关于休眠持久化实体而不获取关联对象。仅凭身份证的主要内容,如果未能解决你的问题,请参考以下文章