我正在使用 Bidirectional @OneToOne
来自hibernate文档。我为测试创建了一个相同的模型。
我无法通过电话详细信息获取电话。我有个错误- Message Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy [com.example.model.Phone#1] - no Session
.
我试过很多方法,但都不管用。
请告诉我如何正确接电话?我坐了一整天试图这样做。我在网上没有找到任何选择,所以我在这里问。 Phone.java
```
@Entity(name = "Phone")
public class Phone {
@Id
@GeneratedValue
private Long id;
@Column(name = "`number`")
private String number;
@OneToOne(mappedBy = "phone",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY)
private PhoneDetails details;
public Phone() {
}
public Phone(String number) {
this.number = number;
}
// Getters and setters are omitted for brevity
public void addDetails(PhoneDetails details) {
details.setPhone( this );
this.details = details;
}
public void removeDetails() {
if ( details != null ) {
details.setPhone( null );
this.details = null;
}
}
}
`PhoneDetails.java`
@Entity(name = "PhoneDetails")
public class PhoneDetails {
@Id
@GeneratedValue
private Long id;
private String provider;
private String technology;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "phone_id")
private Phone phone;
public PhoneDetails() {
}
public PhoneDetails(String provider, String technology) {
this.provider = provider;
this.technology = technology;
}
// Getters and setters are omitted for brevity
}
`LifecycleController.java`
@Controller
public class LifecycleController {
@Autowired
ServiceJpa serviceJpa;
@GetMapping(value = "/savePhoneAndPhoneDetails")
public String savePersonAddress () {
Phone phone = new Phone( "123-456-7890" );
PhoneDetails details = new PhoneDetails( "T-Mobile", "GSM" );
phone.addDetails( details );
serviceJpa.savPhone( phone );
return "/savePhoneAndPhoneDetails";
}
@GetMapping(value = "/getPhone")
public String addPersonAddress () {
PhoneDetails address = serviceJpa.findPhoneDetailsById(2L).orElseThrow();
Phone phone = address.getPhone();
/*
An error appears here -
could not initialize proxy
[com.example.model.Phone#1] - no Session
*/
System.out.println(phone.getNumber());
return "/getPhone";
}
}
`ServiceJpa.java`
@Service
@Transactional
public class ServiceJpa {
@Autowired
PhoneJpa phoneJpa;
@Autowired
PhoneDetailsJpa phoneDetailsJpa;
@Transactional
public void savPhone(Phone phone) {
phoneJpa.save(phone);
}
@Transactional
public Optional<PhoneDetails> findPhoneDetailsById(Long id) {
return phoneDetailsJpa.findById(id);
}
}
接口 `PhoneJpa.java` ```
@Repository
public interface PhoneJpa extends JpaRepository<Phone, Long> {
}
接口 PhoneDetailsJpa.java
```
@Repository
public interface PhoneDetailsJpa extends JpaRepository<PhoneDetails, Long> {
}
![](https://i.stack.imgur.com/qV8Sp.png)
1条答案
按热度按时间siv3szwd1#
我同意andriy的评论,只是稍微加了一句“您不应该在事务边界之外访问[延迟加载的]实体细节”。但是,对于初学者来说,有什么理由让onetoone成为fetchtype.lazy呢?如果你把它改为“渴望”,你的“懒惰”问题将得到解决,因为它不再是一个懒惰的参考,而是一个真正的水合对象。
如果这不是你想要走的确切路线,那么总的来说,有十几种方法可以急切地获取信息,坦率地说,有太多的方法不能将一个单一的解决方案作为最佳/理想的解决方案。由于您的代码是存在的,因为所有的取消引用(目前)都发生在您的控制器中,那么andriy建议将@transaction添加到控制器中就足够了,因为当您需要它时,它将被延迟地获取。
但是在将来,如果pojo中有比控制器更高的惰性元素返回到堆栈中,比如说,就在它们被序列化为json之前,那么即使控制器的@transactional元素在堆栈中也不够“高”,最终也会出现同样的惰性init问题。。
另外,通过让它变得懒惰,然后在其他地方取消引用,可以保证两次访问数据库。使用适当的fetch/join渴望加载,您可以将其限制为一个,这可能是另一个性能优势。
所以不管怎样,你都回到了真正的问题上。。寻找方法来确保您的操作完全发生在事务边界内,或者必须完全冻结对象,这样就不会有“懒惰”的挂起者在事务边界之外被取消引用。。i、 e.通过使他们急切或强制初始化任何潜在的懒惰代理/集合。