FetchType的区别是什么。LAZY和FetchType。Java持久性API中的EAGER ?


当前回答

要理解它们之间的区别,最好的方法是了解lazy-okay。 FetchType。LAZY告诉hibernate在使用关系时只从数据库中获取相关的实体。

p.s.:在我参与过的许多项目中,我看到许多软件开发人员并不重视他们,甚至有人称自己为高级开发人员。如果您正在进行的项目不是在大量数据上进行数据交换,那么在这里使用EAGER是可以的。但是,考虑到可能出现n+1个问题的问题,您需要在默认情况下知道关系的获取类型之后注意这些问题。

这里你可以看到默认值: Hibernate中的默认获取类型为一对一、多对一和一对多

而且,即使在理解了取回类型之后,它也不会就此结束。要理解何时使用LAZY和何时使用EAGER,还需要理解单向和双向的概念。此外,spring引导存储库有一些方法允许它为懒惰或急切的用户读取数据。例如,getOne()或getById()方法允许您从实体中延迟获取数据。简而言之,你用什么,什么时候用,取决于对方想让你做什么。

其他回答

基本上,

LAZY = fetch when needed
EAGER = fetch immediately

默认情况下,对于所有的集合和映射对象,获取规则是FetchType。LAZY,对于其他实例,它遵循FetchType。急切的政策。 简而言之,@OneToMany和@ManyToMany关系并不隐式地获取相关对象(集合和映射),但检索操作通过@OneToOne和@ManyToOne中的字段级联。

(提供:- objectdbcom)

public enum FetchType extends java.lang.Enum Defines strategies for fetching data from the database. The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified. Example: @Basic(fetch=LAZY) protected String getName() { return name; }

我想在上面说的基础上补充这一点。

假设您正在使用Spring (MVC和数据)与这个简单的架构:

Controller <-> Service <-> Repository

如果你使用FetchType,你想返回一些数据到前端。LAZY,在你将数据返回给控制器方法后,你会得到一个LazyInitializationException,因为会话在服务中关闭了,所以JSON Mapper对象无法获得数据。

根据设计、性能和开发人员的不同,有两种常见的方法来解决这个问题:

最简单的方法是使用FetchType。EAGER或任何其他反模式解决方案,使会话仍然活跃在控制器方法,但这些方法将影响性能。 最佳实践是使用FetchType。LAZY使用映射器(如MapStruct)将数据从Entity传输到另一个数据对象DTO,然后将其发送回控制器,因此会话关闭时没有异常。

有一个简单的例子:

@RestController
@RequestMapping("/api")
public class UserResource {

    @GetMapping("/users")
    public Page<UserDTO> getAllUsers(Pageable pageable) {
        return userService.getAllUsers(pageable);
    }
}

@Service
@Transactional
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional(readOnly = true)
    public Page<UserDTO> getAllUsers(Pageable pageable) {
        return userRepository.findAll(pageable).map(UserDTO::new);
    }
}

@Repository
public interface UserRepository extends JpaRepository<User, String> {

    Page<User> findAll(Pageable pageable);
}

public class UserDTO {

    private Long id;

    private String firstName;

    private String lastName;

    private String email;
    
    private Set<String> addresses;

    public UserDTO() {
        // Empty constructor needed for Jackson.
    }

    public UserDTO(User user) {
        this.id = user.getId();
        this.firstName = user.getFirstName();
        this.lastName = user.getLastName();
        this.email = user.getEmail();
        this.addresses = user.getAddresses().stream()
            .map(Address::getAddress)
            .collect(Collectors.toSet());
    }

    // Getters, setters, equals, and hashCode
}

@Entity
@Table(name = "user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String firstName;

    @Column
    private String lastName;

    @Column(unique = true)
    private String email;
    
    @OneToMany(mappedBy = "address", fetch = FetchType.LAZY)
    private Set<Address> addresses = new HashSet<>();

    // Getters, setters, equals, and hashCode
}

@Entity
@Table(name = "address")
public class Address implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String address;

    @ManyToOne
    @JsonIgnoreProperties(value = "addresses", allowSetters = true)
    private User user;

    // Getters, setters, equals, and hashCode
}

I may consider performance and memory utilization. One big difference is that EAGER fetch strategy allows to use fetched data object without session. Why? All data is fetched when eager marked data in the object when session is connected. However, in case of lazy loading strategy, lazy loading marked object does not retrieve data if session is disconnected (after session.close() statement). All that can be made by hibernate proxy. Eager strategy lets data to be still available after closing session.