我有两个实体:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id")
private Person person;
和
@Entity
@Table(name = "persons")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "number")
private String number;
此人为LAZY。我加载了一个用户并将其分离。
@Transactional
@Override
public void run(String... args) {
User user = userService.getOne(1L);
userService.detach(user);
System.out.println(user.getName());
System.out.println(user.getAge());
Person person = user.getPerson();
System.out.println(person.getName());
System.out.println(person.getNumber());
}
但是当我打电话给user.getPerson()
时,它不会引发异常。我期望出现异常,因为我分离了实体并尝试调用LAZY字段,但它仍然有效。
我要创建一个没有用户的用户克隆,并另存为新实体。
User user = userService.getOne(1L);
userService.detach(user);
user.setId(null)//autogenerate id
但是当我保存用户时,人也会克隆。我可以设置为空:
User user = userService.getOne(1L);
userService.detach(user);
user.setId(null);
user.setPerson(null);
但是人很懒,看起来很像黑客。那么detach
方法又有什么意义呢?
编辑:
非常有趣的事情-如果我在调试中使用断点启动示例应用程序-一切正常,但是如果我取消选择所有断点,则会在控制台中出现异常:
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [com.example.detachexample.User#1] - no Session
答案 0 :(得分:0)
据我了解,您是在克隆上调用detach吗?那个克隆不是普通的User对象,而是扩展User对象的代理。
您需要先使用unproxy
获取原始加载的实体。
User olduser = userService.getOne(1L);
User user = org.hibernate.Hibernate.unproxy(olduser);
if (olduser == user) userService.detach(user);
user.setId(null)//autogenerate id
user.getPerson().setId(null); // so you will generate this as well
user.getPerson().setUser(user); // so that it will point to the correct new entity
答案 1 :(得分:0)
似乎在detach
时实际上已经加载了Person
。
根据FetchType
文档,这是可能的:
LAZY策略是对持久性提供程序运行时的提示, 首次访问时应延迟获取数据。的 允许实现急于获取LAZY的数据 策略提示已指定。
因此,请查看Hibernate调试日志,最有可能在某处加入一个Person以及其字段选择。