I'm searching for the best way to optimize Hibernate select
queries.
Here is a basic example:
BDD model 1 Client -> n Contracts -> n Options
The simplest manner to request all data of the client "xxxx" is something like:
final Query hqlQuery = jdbcTemplate.createHQLQuery("from Client cli left join fetch cli.contracts con left join fetch con.options where cli.id=:idClient");
hqlQuery .setString("idClient", "xxxx");
Client client = (Client) hqlQuery.uniqueResult();
Sometimes this is just not possible since there are two much data to return.
So, I split the request, somethink like:
// Query 1
final Query hqlQueryClient = jdbcTemplate.createHQLQuery("from Client cli left join fetch cli.contracts where cli.id=:clientId");
hqlQueryClient.setString("clientId", "xxxx");
Client client = (Client) hqlQueryClient.uniqueResult();
List<String> listContractIds = new ArrayList<String>();
for (Contract contract : client.getContracts()) {
listContractIds.add(contract.getId());
}
// Query 2
final Query hqlQueryOptions = jdbcTemplate.createHQLQuery("from Option opt where opt.contract.id in(:contractIds)");
hqlQueryOptions.setParameterList("contractIds", listContractIds);
List<Option> options = hqlQueryClient.list();
But, with the second manner, I can't "inject" options
in client
object, so I have to deal with client
and options
objects in my code, and search in options
list those which correspond to the contract I'm working with.
Is there a way to complete Hibernate object (client in my example) with values requested in a second time ?
Thanks for your help.
PS: ask if it's not clear, I'm French guy :)
<rant>
I generally hate hibernate because it's such a time waster and also seems to run hundreds of queries when you'd only run a handful if writing the SQL manually <\\rant>
If forced to use hibernate, I'd probably use 3 queries similar to
from Options as o join fetch o.contract as co join fetch co.client as cl where cl = :client
from Contracts as co join fetch co.client as cl where cl = :client
from Client where clientId = :clientId
Then I'd put them all into appropriate Map<Long, List>
maps and do the joins in java.
First: how much data do You have in result that the first query doesn't work? If you the result has so many rows and You want to optimise this query check if all data You get from db You realy need. Maybe You should make a projection to other object which is more flattened.
If you not process the data in Java and only passing it to the front-end consider pageing the result.
The benefit in using Hibernate is ORM. You could set up your classes as Entities. So you don't need to worry about simple queries anymore. Simply use JPA for that task. The entities could look like that:
@Entity
public class Client implements Serializable {
private Long id;
private ArrayList<Contract> contracts;
// more attributes here
@Id @GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany
public ArrayList<Contract> getContracts() {
return contracts;
}
public void setId(Long id) {
this.id = id;
}
public void setContracts(ArrayList<Contract> contracts) {
this.contracts = contracts;
}
}
@Entity
public class Contract implements Serializable {
private Long id;
private List<Option> options;
// more attributes here
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany
public List<Option> getOptions() {
return options;
}
public void setId(Long id) {
this.id = id;
}
public void setOptions(List<Option> options) {
this.options = options;
}
}
and so on...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.