Reputation: 2375
I encounter an optimisation problem and I can't figure out why my query is so slow.
Here my entity :
@Entity
@Table(name = "CLIENT")
public class Client {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "CLIENT_ID")
@SequenceGenerator(name = "ID_GENERATOR", sequenceName = "CLIENT_S", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_GENERATOR")
private Long id;
@Column(name="LOGIN")
private String login;
@Column(name="PASSWORD")
private String password;
And the DAO
@NoRepositoryBean
public interface ClientDao extends JpaRepository<Client, Long>, JpaSpecificationExecutor<Client> {
Client findByPasswordAndLogin(@Param("login") String customerLogin,@Param("password") String customerHashedPassword);
}
When the method findByPasswordAndLogin is executed, it takes about 200ms to be completed (seen both through Junit tests and with JProfiler).
Here the Hibernate query : Hibernate: select clientx0_.CLIENT_ID as CLIENT_ID1_4_, clientx0_.LOGIN as LOGIN9_4_, clientx0_.PASSWORD as PASSWORD10_4_, clientx0_.STATUT as STATUT13_4_ from CLIENT clientx0_ where clientx0_.PASSWORD=? and clientx0_.LOGIN=?
When I execute manually the SQL query on the database, it takes only 3ms :
select * from CLIENT where PASSWORD='xxxxx' and LOGIN='yyyyyyyy'
We have 4000 clients in our development environnement. More than a million in production.
Here the context :
Any idea ?
Upvotes: 1
Views: 5269
Reputation: 2375
I have tested different types of DAO (I don't publish code here because it is so dirty) :
Notes :
I could use :
But :
So :
The Spring JDBCTemplate with RowMapper seems to be the best solution to increase performances on specific case. And we can keep a security on SQL queries. But need to write specific RowMapper to transform ResultSet to Entity.
Example of Spring JDBCTemplate
@Repository
public class ClientJdbcTemplateDao {
private final Logger logger = LoggerFactory.getLogger(ClientJdbcTemplateDao.class);
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<Client> find() {
List<Client> c = this.jdbcTemplate.query( "SELECT login FROM Client WHERE LOGIN='xxxx' AND PASSWORD='xxx'", new ClientRowMapper());
return c;
}
}
Example of Client RowMapper
public class ClientRowMapper implements RowMapper<Client> {
@Override
public Client mapRow(ResultSet arg0, int arg1) throws SQLException {
// HERE IMPLEMENTS THE CONVERTER
// Sample :
// String login = arg0.getString("LOGIN")
// Client client = new Client(login);
// return client;
}
}
Maybe can be better, any suggestion is welcome.
Upvotes: 4