Spring ManyToOne - OneToMany 延迟加载不起作用
Spring ManyToOne - OneToMany Lazy loading not working
我在基于 Spring Boot 2.1.6、Hibernate、MySql、JavaFX、Envers 和 Java 的应用程序上工作了一段时间 8 -没有 Web - 这有助于产品所有者管理需求等。当应用程序启动时,我只想加载所有产品实体,以便产品所有者 select 想要处理哪个产品 he/she。为了确保不从数据库中提取其他相关实体,我尝试实现延迟加载。不幸的是,我的延迟加载注释并没有阻止整个数据库的加载。与我发现的大多数示例不同,我使用的是树结构,即父项和子项具有相同的抽象 class Term.
一切都从
开始
@Controller
public class LoginPaneCtrl {
@Autowired TermService termService;
public void initialize() {
...
List<Product> productList = termService.getAllProducts();
...
}
// rest of class omitted
}
服务 class 看起来像这样
@Service
@Transactional
public class TermService {
@Autowired private ProductRepository productRepository;
public ObservableList<Product> getAllProducts() {
ObservableList<Product> products = FXCollections.observableArrayList();
products.addAll(productRepository.findAll());
return products;
}
// rest of class omitted
}
存储库非常简单
@Repository
@Transactional
public interface ProductRepository extends TermRepository<Product> {
// empty interface
}
和
@NoRepositoryBean
public interface TermRepository<T extends Term> extends JpaRepository<T, Long> {
List<T> findByIdentifier(String indentifier);
List<T> findByGoal(String goal);
List<Product> findByParent(Term parent);
List<T> findAll();
}
产品 class 本身包含对其他实体的多个引用。由于使用 JavaFX,我所有的实体 class 必须是 AccessType.PROPERTY。为了简洁起见,我省略了其中的大部分,但保留了代表性字段..
@Entity
@DiscriminatorValue(Term.PRODUCT)
@Access(AccessType.PROPERTY) // JPA reading and writing attributes through their getter and setter methods
@Audited
public class Product extends Term {
protected StringProperty classification;
protected ObjectProperty<Employee> projectManager;
protected List<Persona> personas; // which type of users will use this product
protected List<Double> marketGrowth;
@ElementCollection
public List<Double> getMarketGrowth() {
return marketGrowth;
}
public void setMarketGrowth(List<Double> marketGrowth) {
this.marketGrowth = FXCollections.observableArrayList(marketGrowth);
}
public String getClassification() {
return classification.get();
}
public void setClassification(String classification) {
this.classification.set(classification);
}
public StringProperty classificationProperty() {
return classification;
}
// Unidirectional. The Employee is not aware of this reference
public Employee getProjectManager() {
return projectManager.get();
}
public void setProjectManager(Employee productOwner) {
this.projectManager.set(productOwner);
}
public ObjectProperty<Employee> projectManagerProperty() {
return projectManager;
}
@OneToMany(fetch = FetchType.LAZY) // Unidirectional mapping
public List<Persona> getPersonas() {
return personas;
}
public void setPersonas(List<Persona> aPersonaList) {
this.personas = FXCollections.observableList(aPersonaList);
}
public void addPersona(Persona aPersona) {
if(! personas.contains(aPersona)) {
personas.add(aPersona);
}
}
public boolean deletePersona(Persona aPersona) {
return personas.remove(aPersona);
}
}
超级class 术语看起来像这样 - 为简洁起见,我省略了大部分字段,但保留了我认为引起问题的字段..
@Entity
@Access (AccessType.PROPERTY) // JPA reading and writing attributes through their getter and setter methods
@Inheritance (strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn ( // In concrete classes @DiscriminatorValue("here the class id")
discriminatorType = DiscriminatorType.STRING,
name = "term_level",
length=10
)
@Audited
public abstract class Term implements Serializable {
private Long id;
/*
* A Term may be broken down into sub-Terms, called children. A child can not be a Term from a higher hierarchical level.
* Between parent and child is a bi-directional relationship
*/
protected ObjectProperty<Term> parent;
protected List<Term> children;
protected ObjectProperty<Term> predecessor;
protected ObjectProperty<Term> successor;
protected List<UserRequirement> requirements;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "termGenerator")
@SequenceGenerator(name="termGenerator", sequenceName = "term_Seq")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne (fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
public Term getParent() {
return parent.get();
}
public void setParent(Term aParent) {
this.parent.set(aParent);
}
public ObjectProperty<Term> parentProperty() {
return parent;
}
@OneToMany(mappedBy="parent", fetch = FetchType.LAZY)
public List<Term> getChildren() {
return children;
}
@PostLoad
/**
* Sorting Terms is difficult due to overlapping release and commercialization trains running in parallel.
* Hence plannedBegin and predecessor/successor information must be evaluated to build a correct order
*/
protected void sortChildren() {
if(children.isEmpty()) {
return;
}
ObservableList<Term >aChildrenList = FXCollections.observableArrayList();
// Step 1: Filter all terms with no predecessor and order by plannedBegin
ArrayList<Term> heads = new ArrayList<>();
for(Term child: children) {
if(child.getPredecessor() == null) {
heads.add(child);
}
}
Comparator<Term> comparator = Comparator.comparing(Term::getPlannedBegin);
Collections.sort(heads, comparator);
// Step 2: Move the other elements to their position depending on successor/predeccessor information
Term successor = null;
for(Term head: heads) {
aChildrenList.add(head);
do {
successor = head.getSuccessor();
if(successor != null) {
int pos = aChildrenList.indexOf(head);
aChildrenList.add(pos+1, successor);
head = successor;
}
} while(successor != null);
}
children = aChildrenList;
}
@SuppressWarnings("unused") // Used by JPA
// The list will be sorted after the entity is set using @PostLoad
protected void setChildren(List<Term> aChildrenList) {
children = aChildrenList;
}
}
查看下面的 SQL 跟踪,在预期的 SQL select 语句之后,查询了所有 Term 子项(classical n+1 problem since lazy loading不工作),然后查询用户需求、他们的角色、下一个测试计划和测试用例等。据我所知,延迟加载在我的整个 class 模型中无处可用,并且加载了整个数据库,尽管我只需要 Product 实体。
Hibernate:
/* select
generatedAlias0
from
Product as generatedAlias0 */ select
product0_.id as id2_59_,
product0_.goal as goal3_59_,
product0_.identifier as identifi4_59_,
product0_.level as level5_59_,
product0_.parent_id as parent_25_59_,
product0_.plannedBegin as plannedB6_59_,
product0_.plannedEnd as plannedE7_59_,
product0_.predecessor_id as predece26_59_,
product0_.state as state8_59_,
product0_.successor_id as success27_59_,
product0_.fk_testplan as fk_test28_59_,
product0_.timeUnit as timeUnit9_59_,
product0_.type as type10_59_,
product0_.version as version11_59_,
product0_.affection as affecti12_59_,
product0_.classification as classif13_59_,
product0_.classificationDirective as classif14_59_,
product0_.intendedUse as intende15_59_,
product0_.negativeImpact as negativ16_59_,
product0_.productLine_id as product29_59_,
product0_.productOwner as product17_59_,
product0_.projectManager as project18_59_,
product0_.purpose as purpose19_59_,
product0_.restriction as restric20_59_,
product0_.systemDescription as systemD21_59_,
product0_.systemEngineer as systemE22_59_,
product0_.technologyReadinessLevel as technol23_59_,
product0_.unlike as unlike24_59_
from
Term product0_
where
product0_.term_level='Product'
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([goal3_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_] : [VARCHAR]) - [first product]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_] : [VARCHAR]) - [Product]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([parent_25_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_] : [DATE]) - [2019-09-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_] : [DATE]) - [2030-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([predece26_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([fk_test28_59_] : [BIGINT]) - [62]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_] : [INTEGER]) - [42]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([affecti12_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([classif13_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([classif14_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([intende15_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([negativ16_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([product29_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([product17_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([project18_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([purpose19_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([restric20_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([systemD21_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([systemE22_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([technol23_59_] : [INTEGER]) - [0]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([unlike24_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.planning.Term.children#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.planning.Term.requirements#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.environmentalInterfaces#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketGrowth#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketSize#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketUnits#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.personas#1]
Hibernate:
select
marketgrow0_.Product_id as Product_1_29_0_,
marketgrow0_.marketGrowth as marketGr2_29_0_
from
Product_marketGrowth marketgrow0_
where
marketgrow0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
marketsize0_.Product_id as Product_1_31_0_,
marketsize0_.marketSize as marketSi2_31_0_
from
Product_marketSize marketsize0_
where
marketsize0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
marketunit0_.Product_id as Product_1_33_0_,
marketunit0_.marketUnits as marketUn2_33_0_
from
Product_marketUnits marketunit0_
where
marketunit0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
children0_.parent_id as parent_25_59_0_,
children0_.id as id2_59_0_,
children0_.id as id2_59_1_,
children0_.goal as goal3_59_1_,
children0_.identifier as identifi4_59_1_,
children0_.level as level5_59_1_,
children0_.parent_id as parent_25_59_1_,
children0_.plannedBegin as plannedB6_59_1_,
children0_.plannedEnd as plannedE7_59_1_,
children0_.predecessor_id as predece26_59_1_,
children0_.state as state8_59_1_,
children0_.successor_id as success27_59_1_,
children0_.fk_testplan as fk_test28_59_1_,
children0_.timeUnit as timeUnit9_59_1_,
children0_.type as type10_59_1_,
children0_.version as version11_59_1_,
children0_.affection as affecti12_59_1_,
children0_.classification as classif13_59_1_,
children0_.classificationDirective as classif14_59_1_,
children0_.intendedUse as intende15_59_1_,
children0_.negativeImpact as negativ16_59_1_,
children0_.productLine_id as product29_59_1_,
children0_.productOwner as product17_59_1_,
children0_.projectManager as project18_59_1_,
children0_.purpose as purpose19_59_1_,
children0_.restriction as restric20_59_1_,
children0_.systemDescription as systemD21_59_1_,
children0_.systemEngineer as systemE22_59_1_,
children0_.technologyReadinessLevel as technol23_59_1_,
children0_.unlike as unlike24_59_1_,
children0_.term_level as term_lev1_59_1_
from
Term children0_
where
children0_.parent_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Product sale and normal maintenance support]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Commercialization]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2022-04-25]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2027-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Discontinue maintenance support. End of sale]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Decommision]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2027-04-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2028-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([goal3_59_1_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [first release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2019-09-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2022-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([predece26_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([fk_test28_59_1_] : [BIGINT]) - [63]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [0]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Product sale and normal maintenance support]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Commercialization]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2024-11-25]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2029-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [19]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [18]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [18]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Discontinue maintenance support. End of sale]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Decommision]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2029-11-26]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2030-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value
...
这持续了 SQL 的 275,000 (!) 行,查询我相信整个数据库。
我知道我可以使用 DTO 解决当前问题,但它不能解决许多其他用例中的问题,因为通常会出现问题。
因此,也请找到我的application.properties
#No JMX needed - disabling it allows for faster startup
spring.jmx.enabled=false
spring.main.banner-mode=off
#no web server needed
spring.main.web-application-type=none
# Properties can be queried in the code e.g. @Value(value = "${spring.datasource.driver-class-name}") private String message;
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1/agiletunesdb?useSSL=false&serverTimezone=Europe/Berlin&useUnicode=true&characterEncoding=utf-8&characterSetResults=utf-8
spring.datasource.username=YYYY
spring.datasource.password=XXXX
# create db schema
#spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.ddl-auto=update
#---- Naming strategy: Use underscore instead of camel case
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#---- Prevent LazyInitializationException
#spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.open-in-view=false
#---- Prevent use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator
spring.jpa.hibernate.use-new-id-generator-mappings=true
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#---- Show sql queries send to db
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
#---- Print SQL statements spread over multiple lines for easier readibility
spring.jpa.properties.hibernate.format_sql=true
我有很多怀疑,但没有证据。也许延迟加载不适用于从@NoRepositoryBean 继承的存储库?也许是parent和child不能派生自同一个superclass?我知道延迟加载是一种 "recommendation" 但我怎么能影响这个决定呢?我假设没有随机化器做出决定 ;-)
请参阅 JB Nizet 评论 - 我将 @PostLoad 移到了控制器中。
我在基于 Spring Boot 2.1.6、Hibernate、MySql、JavaFX、Envers 和 Java 的应用程序上工作了一段时间 8 -没有 Web - 这有助于产品所有者管理需求等。当应用程序启动时,我只想加载所有产品实体,以便产品所有者 select 想要处理哪个产品 he/she。为了确保不从数据库中提取其他相关实体,我尝试实现延迟加载。不幸的是,我的延迟加载注释并没有阻止整个数据库的加载。与我发现的大多数示例不同,我使用的是树结构,即父项和子项具有相同的抽象 class Term.
一切都从
开始@Controller
public class LoginPaneCtrl {
@Autowired TermService termService;
public void initialize() {
...
List<Product> productList = termService.getAllProducts();
...
}
// rest of class omitted
}
服务 class 看起来像这样
@Service
@Transactional
public class TermService {
@Autowired private ProductRepository productRepository;
public ObservableList<Product> getAllProducts() {
ObservableList<Product> products = FXCollections.observableArrayList();
products.addAll(productRepository.findAll());
return products;
}
// rest of class omitted
}
存储库非常简单
@Repository
@Transactional
public interface ProductRepository extends TermRepository<Product> {
// empty interface
}
和
@NoRepositoryBean
public interface TermRepository<T extends Term> extends JpaRepository<T, Long> {
List<T> findByIdentifier(String indentifier);
List<T> findByGoal(String goal);
List<Product> findByParent(Term parent);
List<T> findAll();
}
产品 class 本身包含对其他实体的多个引用。由于使用 JavaFX,我所有的实体 class 必须是 AccessType.PROPERTY。为了简洁起见,我省略了其中的大部分,但保留了代表性字段..
@Entity
@DiscriminatorValue(Term.PRODUCT)
@Access(AccessType.PROPERTY) // JPA reading and writing attributes through their getter and setter methods
@Audited
public class Product extends Term {
protected StringProperty classification;
protected ObjectProperty<Employee> projectManager;
protected List<Persona> personas; // which type of users will use this product
protected List<Double> marketGrowth;
@ElementCollection
public List<Double> getMarketGrowth() {
return marketGrowth;
}
public void setMarketGrowth(List<Double> marketGrowth) {
this.marketGrowth = FXCollections.observableArrayList(marketGrowth);
}
public String getClassification() {
return classification.get();
}
public void setClassification(String classification) {
this.classification.set(classification);
}
public StringProperty classificationProperty() {
return classification;
}
// Unidirectional. The Employee is not aware of this reference
public Employee getProjectManager() {
return projectManager.get();
}
public void setProjectManager(Employee productOwner) {
this.projectManager.set(productOwner);
}
public ObjectProperty<Employee> projectManagerProperty() {
return projectManager;
}
@OneToMany(fetch = FetchType.LAZY) // Unidirectional mapping
public List<Persona> getPersonas() {
return personas;
}
public void setPersonas(List<Persona> aPersonaList) {
this.personas = FXCollections.observableList(aPersonaList);
}
public void addPersona(Persona aPersona) {
if(! personas.contains(aPersona)) {
personas.add(aPersona);
}
}
public boolean deletePersona(Persona aPersona) {
return personas.remove(aPersona);
}
}
超级class 术语看起来像这样 - 为简洁起见,我省略了大部分字段,但保留了我认为引起问题的字段..
@Entity
@Access (AccessType.PROPERTY) // JPA reading and writing attributes through their getter and setter methods
@Inheritance (strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn ( // In concrete classes @DiscriminatorValue("here the class id")
discriminatorType = DiscriminatorType.STRING,
name = "term_level",
length=10
)
@Audited
public abstract class Term implements Serializable {
private Long id;
/*
* A Term may be broken down into sub-Terms, called children. A child can not be a Term from a higher hierarchical level.
* Between parent and child is a bi-directional relationship
*/
protected ObjectProperty<Term> parent;
protected List<Term> children;
protected ObjectProperty<Term> predecessor;
protected ObjectProperty<Term> successor;
protected List<UserRequirement> requirements;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "termGenerator")
@SequenceGenerator(name="termGenerator", sequenceName = "term_Seq")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne (fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
public Term getParent() {
return parent.get();
}
public void setParent(Term aParent) {
this.parent.set(aParent);
}
public ObjectProperty<Term> parentProperty() {
return parent;
}
@OneToMany(mappedBy="parent", fetch = FetchType.LAZY)
public List<Term> getChildren() {
return children;
}
@PostLoad
/**
* Sorting Terms is difficult due to overlapping release and commercialization trains running in parallel.
* Hence plannedBegin and predecessor/successor information must be evaluated to build a correct order
*/
protected void sortChildren() {
if(children.isEmpty()) {
return;
}
ObservableList<Term >aChildrenList = FXCollections.observableArrayList();
// Step 1: Filter all terms with no predecessor and order by plannedBegin
ArrayList<Term> heads = new ArrayList<>();
for(Term child: children) {
if(child.getPredecessor() == null) {
heads.add(child);
}
}
Comparator<Term> comparator = Comparator.comparing(Term::getPlannedBegin);
Collections.sort(heads, comparator);
// Step 2: Move the other elements to their position depending on successor/predeccessor information
Term successor = null;
for(Term head: heads) {
aChildrenList.add(head);
do {
successor = head.getSuccessor();
if(successor != null) {
int pos = aChildrenList.indexOf(head);
aChildrenList.add(pos+1, successor);
head = successor;
}
} while(successor != null);
}
children = aChildrenList;
}
@SuppressWarnings("unused") // Used by JPA
// The list will be sorted after the entity is set using @PostLoad
protected void setChildren(List<Term> aChildrenList) {
children = aChildrenList;
}
}
查看下面的 SQL 跟踪,在预期的 SQL select 语句之后,查询了所有 Term 子项(classical n+1 problem since lazy loading不工作),然后查询用户需求、他们的角色、下一个测试计划和测试用例等。据我所知,延迟加载在我的整个 class 模型中无处可用,并且加载了整个数据库,尽管我只需要 Product 实体。
Hibernate:
/* select
generatedAlias0
from
Product as generatedAlias0 */ select
product0_.id as id2_59_,
product0_.goal as goal3_59_,
product0_.identifier as identifi4_59_,
product0_.level as level5_59_,
product0_.parent_id as parent_25_59_,
product0_.plannedBegin as plannedB6_59_,
product0_.plannedEnd as plannedE7_59_,
product0_.predecessor_id as predece26_59_,
product0_.state as state8_59_,
product0_.successor_id as success27_59_,
product0_.fk_testplan as fk_test28_59_,
product0_.timeUnit as timeUnit9_59_,
product0_.type as type10_59_,
product0_.version as version11_59_,
product0_.affection as affecti12_59_,
product0_.classification as classif13_59_,
product0_.classificationDirective as classif14_59_,
product0_.intendedUse as intende15_59_,
product0_.negativeImpact as negativ16_59_,
product0_.productLine_id as product29_59_,
product0_.productOwner as product17_59_,
product0_.projectManager as project18_59_,
product0_.purpose as purpose19_59_,
product0_.restriction as restric20_59_,
product0_.systemDescription as systemD21_59_,
product0_.systemEngineer as systemE22_59_,
product0_.technologyReadinessLevel as technol23_59_,
product0_.unlike as unlike24_59_
from
Term product0_
where
product0_.term_level='Product'
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([goal3_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_] : [VARCHAR]) - [first product]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_] : [VARCHAR]) - [Product]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([parent_25_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_] : [DATE]) - [2019-09-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_] : [DATE]) - [2030-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([predece26_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([fk_test28_59_] : [BIGINT]) - [62]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_] : [INTEGER]) - [42]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([affecti12_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([classif13_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([classif14_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([intende15_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([negativ16_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([product29_59_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([product17_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([project18_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([purpose19_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([restric20_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([systemD21_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([systemE22_59_] : [VARBINARY]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([technol23_59_] : [INTEGER]) - [0]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([unlike24_59_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.planning.Term.children#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.planning.Term.requirements#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.environmentalInterfaces#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketGrowth#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketSize#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.marketUnits#1]
TRACE 14:07 o.h.t.CollectionType.getCollection:813: Created collection wrapper: [com.agiletunes.shared.domain.portfolio.Product.personas#1]
Hibernate:
select
marketgrow0_.Product_id as Product_1_29_0_,
marketgrow0_.marketGrowth as marketGr2_29_0_
from
Product_marketGrowth marketgrow0_
where
marketgrow0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
marketsize0_.Product_id as Product_1_31_0_,
marketsize0_.marketSize as marketSi2_31_0_
from
Product_marketSize marketsize0_
where
marketsize0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
marketunit0_.Product_id as Product_1_33_0_,
marketunit0_.marketUnits as marketUn2_33_0_
from
Product_marketUnits marketunit0_
where
marketunit0_.Product_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
Hibernate:
select
children0_.parent_id as parent_25_59_0_,
children0_.id as id2_59_0_,
children0_.id as id2_59_1_,
children0_.goal as goal3_59_1_,
children0_.identifier as identifi4_59_1_,
children0_.level as level5_59_1_,
children0_.parent_id as parent_25_59_1_,
children0_.plannedBegin as plannedB6_59_1_,
children0_.plannedEnd as plannedE7_59_1_,
children0_.predecessor_id as predece26_59_1_,
children0_.state as state8_59_1_,
children0_.successor_id as success27_59_1_,
children0_.fk_testplan as fk_test28_59_1_,
children0_.timeUnit as timeUnit9_59_1_,
children0_.type as type10_59_1_,
children0_.version as version11_59_1_,
children0_.affection as affecti12_59_1_,
children0_.classification as classif13_59_1_,
children0_.classificationDirective as classif14_59_1_,
children0_.intendedUse as intende15_59_1_,
children0_.negativeImpact as negativ16_59_1_,
children0_.productLine_id as product29_59_1_,
children0_.productOwner as product17_59_1_,
children0_.projectManager as project18_59_1_,
children0_.purpose as purpose19_59_1_,
children0_.restriction as restric20_59_1_,
children0_.systemDescription as systemD21_59_1_,
children0_.systemEngineer as systemE22_59_1_,
children0_.technologyReadinessLevel as technol23_59_1_,
children0_.unlike as unlike24_59_1_,
children0_.term_level as term_lev1_59_1_
from
Term children0_
where
children0_.parent_id=?
TRACE 14:07 o.h.t.d.s.BasicBinder.bind:65: binding parameter [1] as [BIGINT] - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Product sale and normal maintenance support]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Commercialization]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2022-04-25]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2027-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Discontinue maintenance support. End of sale]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Decommision]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2027-04-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2028-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [9]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([goal3_59_1_] : [VARCHAR]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [first release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Release]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2019-09-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2022-04-22]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([predece26_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [8]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([fk_test28_59_1_] : [BIGINT]) - [63]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [0]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [10]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Product sale and normal maintenance support]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Commercialization]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2024-11-25]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2029-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [19]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([success27_59_1_] : [BIGINT]) - [18]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_0_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_0_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([id2_59_1_] : [BIGINT]) - [18]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([term_lev1_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([goal3_59_1_] : [VARCHAR]) - [Discontinue maintenance support. End of sale]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([identifi4_59_1_] : [VARCHAR]) - [Decommision]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([level5_59_1_] : [VARCHAR]) - [Phase]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([parent_25_59_1_] : [BIGINT]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedB6_59_1_] : [DATE]) - [2029-11-26]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([plannedE7_59_1_] : [DATE]) - [2030-11-23]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([predece26_59_1_] : [BIGINT]) - [17]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([success27_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:51: extracted value ([fk_test28_59_1_] : [BIGINT]) - [null]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value ([version11_59_1_] : [INTEGER]) - [1]
TRACE 14:07 o.h.t.d.s.BasicExtractor.extract:61: extracted value
...
这持续了 SQL 的 275,000 (!) 行,查询我相信整个数据库。
我知道我可以使用 DTO 解决当前问题,但它不能解决许多其他用例中的问题,因为通常会出现问题。
因此,也请找到我的application.properties
#No JMX needed - disabling it allows for faster startup
spring.jmx.enabled=false
spring.main.banner-mode=off
#no web server needed
spring.main.web-application-type=none
# Properties can be queried in the code e.g. @Value(value = "${spring.datasource.driver-class-name}") private String message;
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1/agiletunesdb?useSSL=false&serverTimezone=Europe/Berlin&useUnicode=true&characterEncoding=utf-8&characterSetResults=utf-8
spring.datasource.username=YYYY
spring.datasource.password=XXXX
# create db schema
#spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.ddl-auto=update
#---- Naming strategy: Use underscore instead of camel case
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#---- Prevent LazyInitializationException
#spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.open-in-view=false
#---- Prevent use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator
spring.jpa.hibernate.use-new-id-generator-mappings=true
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#---- Show sql queries send to db
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
#---- Print SQL statements spread over multiple lines for easier readibility
spring.jpa.properties.hibernate.format_sql=true
我有很多怀疑,但没有证据。也许延迟加载不适用于从@NoRepositoryBean 继承的存储库?也许是parent和child不能派生自同一个superclass?我知道延迟加载是一种 "recommendation" 但我怎么能影响这个决定呢?我假设没有随机化器做出决定 ;-)
请参阅 JB Nizet 评论 - 我将 @PostLoad 移到了控制器中。