I have following method to extract data from DB table
public User getNextUser() {
final EntityManager em = getEntityManagerFactory().createEntityManager();
final String sql = "UPDATE user " +
"SET processing = TRUE " +
"WHERE id = (" +
"SELECT id " +
"FROM user " +
"WHERE processing = FALSE " +
"LIMIT 1 FOR UPDATE) " +
"RETURNING *";
final Query query = em.createNativeQuery(sql, User.class);
User result = null;
try {
List userList = query.getResultList();
if (!userList.isEmpty()) {
result = (User) userList.get(0);
}
} finally {
em.close();
}
return result;
}
How it's possible to convert this native query to Hibernate query (to not invalidate 2nd level cache)? I have read that equivalent of
SELECT ... FOR UPDATE
in Hibernate it's possible to implement via
PESSIMISTIC_WRITE
Related
I have this SQL code generated by JHipster which I need to modify:
RowsFetchSpec<Employees> createQuery(Pageable pageable, Criteria criteria) {
List<Expression> columns = EmployeesSqlHelper.getColumns(entityTable, EntityManager.ENTITY_ALIAS);
columns.addAll(AccountsSqlHelper.getColumns(accountTable, "account"));
columns.addAll(RolesSqlHelper.getColumns(roleTable, "role"));
SelectFromAndJoinCondition selectFrom = Select
.builder()
.select(columns)
.from(entityTable)
.leftOuterJoin(accountTable)
......
.equals(Column.create("id", roleTable));
String select = entityManager.createSelect(selectFrom, Employees.class, pageable, criteria);
String alias = entityTable.getReferenceName().getReference();
String selectWhere = Optional.ofNullable(criteria).map(crit -> select + " " + "WHERE" + " " + alias + "." + crit).orElse(select); // TODO remove once https://github.com/spring-projects/spring-data-jdbc/issues/907 will be fixed
return db.sql(selectWhere).map(this::process);
}
private Employees process(Row row, RowMetadata metadata) {
Employees entity = employeesMapper.apply(row, "e");
entity.setAccount(accountsMapper.apply(row, "account"));
entity.setRole(rolesMapper.apply(row, "role"));
return entity;
}
As you can see the second Java method populates inner JSON code block.
I need to replace this code with this SQL code:
#Query("SELECT * " +
" FROM employees e " +
..........
"LIMIT :limit " +
"OFFSET :offset")
Flux<Employees> findAllByInstAccountParam(#Param("params") String params, #Param("limit") long limit, #Param("offset") long offset);
How I apply the Java method process after executing the SQL query for findAllByInstAccountParam?
I use this code to make SQL request to find DB record:
public Optional<Subscription> findSubscriptionsByUserEmail(String email) {
String hql = "SELECT s " +
"FROM " + Subscription.class.getName() + " s " +
"INNER JOIN " + Orders.class.getName() + " o ON s.orderId = o.id " +
"INNER JOIN " + Users.class.getName() + " u ON u.id = o.userId " +
"WHERE u.email = :email " +
"ORDER BY s.createdAt DESC ";
TypedQuery<Subscription> query = entityManager.createQuery(hql, Subscription.class).setMaxResults(1).setParameter("email", email);
Optional<Subscription> subscription = Optional.of(query.getSingleResult());
return subscription;
}
But when I don't have a record I get exception: No entity found for query
Do you know how I can skip this exception and continue code execution?
The simplest way to do it is either to try/catch the optional object to see there has been a data sent back or make simple check to see if the optional has an object in it.
Eg:
!subscription.isPresent()? null:subscription;
I am creating the Spring Boot application with a PostgreSQL database. and I am using JDBCTemplate to perform DB operations. as per my requirement, I want a count of the row from CONTRACT_VIEW_2 table where the value of LICENSE_PLATE = "xxxxxx" and ZONE_CODE is IN ("x","y","z") but I am getting PSQL Exception.
I tried using MapSQLParameterSource but still, I facing the issue.
#Override
public Integer getAllZoneForLp(String lp,List<String> zones) {
MapSqlParameterSource zoneIds = new MapSqlParameterSource();
zoneIds.addValue("zoneIds",zones);
String sql = "select " +
"count(*) " +
"from contract_view_2 " +
"where license_plate = ? and zone_code IN (?)";
return jdbcTemplate.queryForObject(sql,Integer.class,lp,zoneIds);
}
I expect the row count in the result but I am getting PSQL Exception. I am attaching the image of the exception which I am getting.
Thanks in advance.
The problem with yours is you have added Namedparameter to JdbcTemplate.
So in case you are using NamedParameterJdbcTemplate
#Override
public Integer getAllZoneForLp(String lp,List<String> zones) {
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("lp", lp);
parameters.addValue("zoneIds",zones);
String sql = "select " +
"count(*) " +
"from contract_view_2 " +
"where license_plate = :lp and zone_code IN (:zoneIds)";
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
return namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class);
}
In case you want to use jdbcTemplate
#Override
public Integer getAllZoneForLp(String lp,List<String> zones) {
String sql = "select " +
"count(*) " +
"from contract_view_2 " +
"where license_plate = ? and zone_code IN (?)";
return jdbcTemplate.queryForObject(sql, Integer.class, new Object[] { lp, zones});
}
Go with NameParameterJdbcTemplate so that you won't miss any params.
Please change your query to
String sql = "select " +
"count(*) " +
"from contract_view_2 " +
"where license_plate = ? and zone_code IN (:zoneIds)";
Changes: changed ? to :zoneIds
Line zoneIds.addValue("zoneIds",zones); is using named parameter to bind it.
I am developing an application that can update my database... However, I can't get my Java method working correctly. It gives me the following error: Must declare the scalar variable "#P0WHERE". Any suggestions?
The method I am using:
public void updateTable() throws SQLException
{
Scanner input = new Scanner(System.in);
System.out.println("Update the following:\n" + this);
this.getReservationInfo(input);
DataConnection connection = new DataConnection();
String query = "UPDATE " + TableName;
query += "Set Name = ?";
query += "WHERE Person_ID = " + id;
connection.updateData(query, person_name);
connection.closeConnection();
}
Add spaces before 'SET' and 'WHERE', otherwise it will not work.
String query = "UPDATE " + TableName;
query += " SET Name = ?";
query += " , Age = ?";
query += " , Col1 = ?"; //And other cols
query += " WHERE Person_ID = " + id;
EDIT: Changed query to update multiple columns.
I think so. You seem to be missing spaces. After the TableName and after the ?.
String query = "UPDATE " + TableName;
query += " Set Name = ?"; // tableSet not good, and
// ?WHERE is not valid add spaces.
query += " WHERE Person_ID = " + id;
This code using JPA2 criteria query return an empty result list:
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<VwReplPrevia> query = criteriaBuilder.createQuery(VwReplPrevia.class);
Root<VwReplPrevia> root = query.from(VwReplPrevia.class);
query.multiselect(root.get(VwReplPrevia_.codigoCentroCustos),
root.get(VwReplPrevia_.numeroCartaoPostagem),
root.get(VwReplPrevia_.codigoServico),
root.get(VwReplPrevia_.quantidadeItems),
root.get(VwReplPrevia_.valorServico));
TypedQuery<VwReplPrevia> typedQuery = getEntityManager().createQuery(query);
String contrato = StringUtils.trim(paginador.getEntityBean().getContrato());
String centroCustos = StringUtils.trim(paginador.getEntityBean().getCentroCustos());
String cartaoPostagem = StringUtils.trim(paginador.getEntityBean().getCartaoPostagem());
String servico = StringUtils.trim(paginador.getEntityBean().getServico());
query.where(criteriaBuilder.equal(root.get(VwReplPrevia_.numeroContrato), contrato));
if (StringUtils.isNotBlank(centroCustos)) {
criteriaBuilder.and(criteriaBuilder.equal(root.get(VwReplPrevia_.codigoCentroCustos), "9912231583"));
}
if (StringUtils.isNotBlank(cartaoPostagem)) {
criteriaBuilder.and(criteriaBuilder.equal(root.get(VwReplPrevia_.numeroCartaoPostagem), cartaoPostagem));
}
if (StringUtils.isNotBlank(servico)) {
criteriaBuilder.and(criteriaBuilder.equal(root.get(VwReplPrevia_.codigoServico), servico));
}
query.orderBy(criteriaBuilder.asc(root.get(VwReplPrevia_.codigoCentroCustos)));
query.groupBy(root.get(VwReplPrevia_.codigoCentroCustos),
root.get(VwReplPrevia_.numeroCartaoPostagem),
root.get(VwReplPrevia_.codigoServico),
root.get(VwReplPrevia_.quantidadeItems),
root.get(VwReplPrevia_.valorServico));
List<VwReplPrevia> resultado = typedQuery.getResultList();
The same query, using native query, return the corret number of results.
String sql = "SELECT vwreplprev0_.sdan8 AS col_0_0_, " +
"vwreplprev0_.sdcnid AS col_1_0_, " +
"vwreplprev0_.sdlitm AS col_2_0_, " +
"vwreplprev0_.sduorg AS col_3_0_, " +
"vwreplprev0_.sdaexp AS col_4_0_ " +
"FROM sfe_view.vw_f4211_repl_previa vwreplprev0_ " +
"WHERE vwreplprev0_.sddmct = '9912231583' " +
"GROUP BY vwreplprev0_.sdan8, " +
"vwreplprev0_.sdcnid, " +
"vwreplprev0_.sdlitm, " +
"vwreplprev0_.sduorg, " +
"vwreplprev0_.sdaexp " +
"ORDER BY vwreplprev0_.sdan8 ASC ";
Collection<PreviaFaturaBean> result = getEntityManager().createNativeQuery(sql).getResultList();
paginador.setColecaoDeRegistros(result);
I have no idea what's the problem. My only reference in implementing via Criteria Query was http://docs.oracle.com/javaee/6/tutorial/doc/gjivm.html, someone can give me a hint?
The following part looks wrong, and not matching with the native query:
query.where(criteriaBuilder.equal(root.get(VwReplPrevia_.numeroContrato), contrato));
if (StringUtils.isNotBlank(centroCustos)) {
criteriaBuilder.and(criteriaBuilder.equal(root.get(VwReplPrevia_.codigoCentroCustos), "9912231583"));
}
It should probably be
query.where(criteriaBuilder.equal(root.get(VwReplPrevia_.numeroContrato), "9912231583"));
if (StringUtils.isNotBlank(centroCustos)) {
criteriaBuilder.and(criteriaBuilder.equal(root.get(VwReplPrevia_.codigoCentroCustos), centroCustos));
}
If that's not the problem, see which SQL query is generated in the logs by your JPA engine, and compare it with the native query to find what the difference is.