双向@onetoone spring数据jpa,hibernate

jfewjypa  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(427)

我正在使用 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)
siv3szwd

siv3szwd1#

我同意andriy的评论,只是稍微加了一句“您不应该在事务边界之外访问[延迟加载的]实体细节”。但是,对于初学者来说,有什么理由让onetoone成为fetchtype.lazy呢?如果你把它改为“渴望”,你的“懒惰”问题将得到解决,因为它不再是一个懒惰的参考,而是一个真正的水合对象。
如果这不是你想要走的确切路线,那么总的来说,有十几种方法可以急切地获取信息,坦率地说,有太多的方法不能将一个单一的解决方案作为最佳/理想的解决方案。由于您的代码是存在的,因为所有的取消引用(目前)都发生在您的控制器中,那么andriy建议将@transaction添加到控制器中就足够了,因为当您需要它时,它将被延迟地获取。
但是在将来,如果pojo中有比控制器更高的惰性元素返回到堆栈中,比如说,就在它们被序列化为json之前,那么即使控制器的@transactional元素在堆栈中也不够“高”,最终也会出现同样的惰性init问题。。
另外,通过让它变得懒惰,然后在其他地方取消引用,可以保证两次访问数据库。使用适当的fetch/join渴望加载,您可以将其限制为一个,这可能是另一个性能优势。
所以不管怎样,你都回到了真正的问题上。。寻找方法来确保您的操作完全发生在事务边界内,或者必须完全冻结对象,这样就不会有“懒惰”的挂起者在事务边界之外被取消引用。。i、 e.通过使他们急切或强制初始化任何潜在的懒惰代理/集合。

相关问题