Hibernate n+1 problem

Stored in the Session cache is a graph of interrelated objects. By default, when Hibernate loads a Customer object from the database, it loads all associated Order objects at the same time. Take the Customer and Order classes as examples, assuming that the CUSTOMER_ID foreign key of the ORDERS table is allowed to be null
, the find() method of the following Session is used to retrieve all Customer objects from the database:
List customerLists=session.find("from Customer as c") ;
When the above find() method is run, Hibernate will first query all records in the CUSTOMERS table, and then according to the ID of each record, to query the records with reference relationship in the ORDERS table, Hibernate will execute the following select statements in sequence:
select * from CUSTOMERS;
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
select * from ORDERS where CUSTOMER_ID=4;
Through the above 5 select statements, Hibernate finally loaded 4 A Customer object and five Order objects form an associated object graph in memory.
Hibernate uses the default immediate retrieval strategy when retrieving the Order object associated with the Customer. This retrieval strategy has two major drawbacks:
(1) The number of select statements is too large, which requires frequent access to the database, which will affect the retrieval performance. If you need to query n Customer objects, you must execute n+1 select query statements. This is the classic n+1 select query problem. This retrieval strategy does not use the connection query function of SQL. For example, the above five select statements can be completed by the following one select statement:
select * from CUSTOMERS left outer join ORDERS
on CUSTOMERS.ID=ORDERS.CUSTOMER_ID The
above select statement uses The left outer join query function of SQL can query all the records of the CUSTOMERS table and the matching records of the ORDERS table in a select statement.
(2) When the application logic only needs to access the Customer object and does not need to access the Order object, loading the Order object is completely redundant, and these redundant Order objects waste a lot of memory space.
In order to solve the above problems, Hibernate provides two other retrieval strategies: lazy retrieval strategy and urgent left outer join retrieval strategy. The delayed retrieval strategy can avoid redundant loading of associated objects that the application does not need to access. The urgent left outer join retrieval strategy makes full use of the outer join query function of SQL, which can reduce the number of select statements.
Performance issues must be considered for database access. After setting a 1-to-many relationship, the legendary n+1 problem will occur in the query.
1) 1-to-many, on the 1 side, n objects are found in the search, then the set associated with the n objects needs to be taken out, so the original SQL query becomes n +
1. 2) Many-to-1, in the multi-party , the query obtains m objects, then the object of the 1 side corresponding to the m objects will also be taken out, which also becomes m+1
. How to solve the n+1 problem?
1) lazy=true, hibernate3 has defaulted to lazy=true at the beginning; when lazy=true, the associated object will not be queried immediately, and the query action will only occur when the associated object (access its properties, non-id fields) is required.
2) Level 2 cache, when the number of object updates, deletions, and additions is much less than that of queries, the application of level 2 cache will not be afraid of the n +1 problem, because even if the first query is very slow, the direct cache hit is very fast afterwards .
Different solutions, different ideas, but the second one just uses n +1 again.
3) Of course you can also set fetch=join(annotation : @ManyToOne() @Fetch(FetchMode.JOIN))

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326545617&siteId=291194637