FetchType的区别是什么。LAZY和FetchType。Java持久性API中的EAGER ?
当前回答
我想在上面说的基础上补充这一点。
假设您正在使用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
}
其他回答
JOIN很重要
轻松地看待它:
假设我们有一个叫User的类和另一个叫Address的类,假设每个用户都有一个或多个地址,意思是关系(一对多),如果执行:
FetchType。LAZY执行sql命令,就像没有join一样:
SELECT * FROM users
FetchType。执行sql命令:
SELECT * FROM users u join address a on a.user_id = u.user_id
注意:以上查询只是为您澄清图像,但Hibernate框架实际执行的查询与上述查询类似。
哪种获取类型更好?
由于Eager抓取会自动加载所有关系,这是一个很大的性能消耗 除非被告知,否则惰性抓取不会加载任何关系,这将带来更好的性能 即时抓取使得编程更容易,因为需要的代码更少 如果整个系统没有经过适当的测试,延迟加载可能会导致错误(异常) 考虑到所有因素,您仍然应该更喜欢Lazy加载而不是Eager加载,因为它的性能更好
如果你正在使用Spring引导框架,那么就进入应用程序。属性文件并添加下面的命令以了解到底发生了什么。
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
这两种类型的抓取之间的主要区别是数据加载到内存中的时刻。 我附上了2张照片来帮助你理解这一点。
急于获取
延迟获取
据我所知,这两种类型的取回取决于你的要求。
FetchType。LAZY是按需的(即当我们需要数据时)。
FetchType。EAGER是即时的(即在我们的需求到来之前,我们不必要地获取记录)
默认情况下,对于所有的集合和映射对象,获取规则是FetchType。LAZY,对于其他实例,它遵循FetchType。急切的政策。 简而言之,@OneToMany和@ManyToMany关系并不隐式地获取相关对象(集合和映射),但检索操作通过@OneToOne和@ManyToOne中的字段级联。
(提供:- objectdbcom)
我想在上面说的基础上补充这一点。
假设您正在使用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
}
推荐文章
- 如何在java中格式化持续时间?(如格式H:MM:SS)
- urlencoder .encode(字符串)已弃用,我应该使用什么代替?
- javax.transaction.Transactional vs . org.springframework.transaction.annotation.Transactional
- Java 8接口方法中不允许“同步”的原因是什么?
- 如何找到Java堆大小和内存使用(Linux)?
- Spring引导——不是托管类型
- 使用Enum实现单例(Java)
- RabbitMQ与通道和连接之间的关系
- buildSessionFactory()配置方法在Hibernate中已弃用?
- Spring MVC -如何获得所有的请求参数在一个地图在Spring控制器?
- 如何在Java中按两个字段排序?
- 文件之间的差异。路径中的分隔符和斜杠
- 在方法参数中使用NotNull注释
- Spring MVC中处理可选参数的@RequestParam
- Tomcat:如何查找正在运行的Tomcat版本?