【发布时间】:2021-07-14 11:23:09
【问题描述】:
我正在使用来自Hibernate documentation 的Bidirectional @OneToOne。我为测试创建了一个相同的模型。
我无法通过 PhoneDetails 获取电话。我收到一个错误 - 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> {
}
【问题讨论】:
-
通过添加注释 @Transactional 使您的 ServiceJpa 具有事务性
-
我做到了。它没有帮助。
-
请在问题中添加您的 ServiceJpa 代码
-
我添加了。请看。
-
您不应访问事务范围之外的实体详细信息。好吧,作为一种快速而肮脏的技巧,您可以将@Transaction 放在控制器级别。正确的解决方案是将实体映射到DTO表示,参考我的文章github.com/slobodator/hibernate-probe#entity-and-dto
标签: spring hibernate spring-data-jpa spring-data hibernate-mapping