我面临两个问题:N 1查询和内存不足(OOM)。
我通过分页和延迟加载解决了OOM问题:
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Set<Employee> employees;
但当我使用延迟加载时,出现了N 1查询。因此,我尝试使用EntityGraph作为https://www.baeldung.com/spring-data-jpa-named-entity-graphs.但在我的研究和本地测试中,EntityGraph总是对NamedAttributeNode字段-关联字段(我想延迟加载)进行急切加载,而不是首先加载所有数据:
@Entity
@Table(name = "department")
@NamedEntityGraph(name = "Department",
attributeNodes = {
@NamedAttributeNode("employees")
}
)
public class Department implements Serializable {
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Set<Employee> employees;
}
那么有什么方法可以同时获得它们吗?使用EntityGraph
避免N 1和延迟加载以避免OOM?
更新:EntityGraph能否有效地与Pageable配合使用?我的意思是不要在连接查询中加载所有数据。
一个简单的解决方案是:
@EntityGraph
的记录。@EntityGraph
从以前返回的id中获取您的记录。=
例子:
在主存储库中,添加带有要获取的关联的EntityGraph注释:
java prettyprint-override">public interface CarRepository extends JpaRepository<Car, String>, JpaSpecificationExecutor<Car>, CarCustomRepository {
@Override
@EntityGraph(attributePaths = { "foo", "bar", "bar.baz" })
List<Car> findAllById(Iterable<String> ids);
}
使用findAllWithEntityGraph方法创建自定义存储库:
public interface CarCustomRepository {
Page<Car> findAllWithEntityGraph(Specification<Car> specification, Pageable pageable);
}
自定义存储库的实现。它首先获取没有实体图的实体,然后使用实体图重新获取它们以加载关联。不要忘记对实体重新排序以保持顺序:
public class CarCustomRepositoryImpl implements CarCustomRepository {
@Autowired
@Lazy
private CarRepository carRepository;
@Override
public Page<Car> findAllWithEntityGraph(Specification<Car> specification, Pageable pageable) {
Page<Car> page = carRepository.findAll(specification, pageable);
List<String> ids = page.getContent().stream().map(Car::getId).collect(Collectors.toList());
List<Car> cars = carRepository.findAllById(ids).stream()
.sorted(Comparator.comparing(car -> ids.indexOf(car.getId())))
.collect(Collectors.toList());
return new PageImpl<>(cars, pageable, page.getTotalElements());
}
}
然后,您只需调用CarRepository#findAllSusEntityGraph
方法即可获取具有分页且没有N 1复杂性的记录。
问题是:为什么hibernate在默认情况下没有这种行为?
使用EntityGraph,您的所有关联都将加载到带有Join子句的1个查询中。启用sql日志以查看hibernate在不同场景中加载实体的查询数
logging.level.org.hibernate.SQL=DEBUG
您将看到,在不使用实体图的情况下,使用OneToMany(fetch=FetchType.EAGER)可以在单独的选择查询中加载员工(N 1),但使用实体图只执行1选择。。。加入
也不要忘记在存储库中指定实体图名称,例如:
@EntityGraph(value = "Department")
List<Department> findAll();
更新:Spring数据分页在数据库端不起作用。它将获取所有数据,然后在内存中进行过滤。这就是它的工作原理。。有一些解决方法,请检查以下链接:
使用Hibernate时,如何避免使用集合获取指定的警告“firstResult/max结果;在内存中应用!”?
避免“HH000104:使用集合获取指定的firstResult/maxResults;在内存中应用!”使用Spring数据
VladMihalcea博客修复Hibernate HHH000104的最佳方法
对我来说,解决方案可能是创建自定义存储库并使用EntityManager
手动构建查询。
我两个月前刚开始学习Spring,以前从未做过Ajax或JavaScript。所以我对这个很陌生。我想做的是从控制器中的GET方法加载数据,将其填充到模式中。我正在使用ajax来实现这一点。基本上我做了这家伙做的事https://qtzar.com/2017/03/24/ajax-and-thymeleaf-for-modal-dialogs/正在做。但它不起作用。 希望有人能帮我。 这是我的控制
我有个小问题。假设我有这个实体: 因为在某些时候我不想加载名字和姓氏,所以我使用了投影(https://docs.spring.io/spring-data/jpa/docs/1.10.2.release/reference/html/#Projections):我定义了这个接口: 现在来看看这个存储库: 所以基本上Spring加载所有字段。如果在PersonSlim接口中排除方法,Spring将
描述 (Description) 延迟加载延迟一个给定的网页上您的图像加载过程。 延迟加载滚动提高性能,加快页面加载,节省流量。 懒惰负载元件和图像必须是内部滚动正常工作。 下表显示了使用延迟加载的 - S.No 懒惰负载和使用说明 1 Usage 延迟加载可以应用到图像,背景图像和与淡入效果。 2 Init Lazy Load Manually 初始化页面后,如果您添加延迟加载图像手动然后,延迟
另外,我将.kt反编译回Java。在companion类中,我得到以下代码。 } 1)如何通过在kotlin同伴对象中使用lateinit或lazy来实现线程安全、单例?正如我所看到的,反编译的java代码在initialize函数中有一个synchronized调用,但在synchronize正文中没有。
有什么方法可以声明惰性加载队列吗?
对象文件: 零件文件: 用于加载数据的密码命令行: neo4j2.1.7和neo4j2.2.0-M04都存在此问题。