I have coded a method which selects or updates a value if it has a certain identifier:
#Transactional
public List<Settings> getSettingsByParameter(String identifier) throws Exception {
log.info("get resultsList by " + identifier);
if(identifier.isEmpty()) {
throw new Exception("Identifier is empty!");
}
if(identifier == "today") {
//update today field
String query = "UPDATE settings SET value=TODAY() where identifier = '" + identifier + "'";
em.merge(em.createQuery(query, Settings.class).getSingleResult());
}
String query = "SELECT p FROM Settings p WHERE identifier = '" + identifier + "'";
List<Settings> resultList = em.createQuery(query, Settings.class).getResultList();
return resultList;
}
However, I am getting an exception:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: settings is not mapped [UPDATE settings SET value=TODAY() where identifier = 'today']
Why and how is this possible using hibernate and hsqldb?
I really appreciate your answer!
Hibernate is case-sensitive with class names. Try it with a captial S for the Settings class:
String query = "UPDATE Settings SET value=TODAY() where identifier = '" + identifier + "'";
Related
I need to create a room database query dynamically because I have lots of fields for UPDATE in the database.
If I used like below method then it works, but I have lots of fields that's why I can't create a separate UPDATE method like this.
#Query("UPDATE PROCEDUREMODEL SET patient_in_time = :val WHERE procedure_sr_number LIKE :sr")
void updateP(String val, String sr);
Now I try below but it does not work.
In DAO class I created this
#RawQuery
ProcedureModel updateProcedure(SupportSQLiteQuery supportSQLiteQuery);
And use like this
public static void updateProcedure(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
SupportSQLiteQuery supportSQLiteQuery = new SimpleSQLiteQuery(s);
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(supportSQLiteQuery);
});
thread.start();
}
I want to run the UPDATE query at runtime in Room database.
I believe that your issue is with the SQL being passed:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = :" + val + " WHERE procedure_sr_number LIKE :" + id;
As the value val is non-numeric, because of the :'s (which you probably don't want), likewise for the id (if not numeric) the values should be enclosed in single quotes.
So using:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = ':" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
would work. Although you very likely don't want the : as part of the value so you very likely want:-
String s = "UPDATE PROCEDUREMODEL SET " + colName + " = '" + val + "' WHERE procedure_sr_number LIKE '" + id + "'";
Saying that it is not recommended to apply literal values via string concatenation but to utilise parameter binding. This protects against SQL injection. As such you may wish to consider the following version:-
public static void updateProcedureBetter(Context context, String colName, String val, String id) {
String s = "UPDATE PROCEDUREMODEL SET " + colName + "=? WHERE procedure_sr_number LIKE ?";
Thread thread = new Thread(() -> {
DatabaseHelper.getInstance(context).getDao().updateProcedure(new SimpleSQLiteQuery(s,new Object[]{val,id}));
});
thread.start();
}
notice the ?'s in the SQL these being replaced by the objects in the Object[], the values being properly enclosed by SQLite parameter binding.
the replacement is on a 1 by/for 1 basis (first ? replace by first object in array, 2nd ? by second object ....)
note also that the intermediate supportSQLiteQuery object has been done away with.
component names (tables, columns etc) typically cannot be bound/changed so the column name has to be concatenated.
Can someone help me to have a look at what is wrong with my query?
Java code :
public boolean fValidLogin(String fUsername, String fPassword) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
String query = "SELECT fusername,fpassword FROM flogin WHERE fusername=" + fUsername + " AND fpassword=" + fPassword + "";
Query DBquery = session.createQuery(query);
for (Iterator it = DBquery.iterate(); it.hasNext();) {
it.next();
count++;
}
System.out.println("Total rows: " + count);
if (count == 1) {
return true;
} else {
return false;
}
}
MYSQL Code:
SELECT fusername,fpassword FROM flogin WHERE fusername="SAS" AND fpassword="Sas123"
Try this first:
"SELECT fusername,fpassword FROM flogin WHERE fusername=\"" + fUsername + "\" AND fpassword=\"" +fPassword +"\""
By the way you are tring to use a native query. Maybe you should consider to use "createNativeQuery" instead of "createQuery"
Your query is a victim of an SQL Injection, it can also cause syntax error, instead you have to use setParameter with a JPQL query :
String query = "SELECT f FROM flogin f WHERE f.fusername = ? AND f.fpassword = ?";
Query dBquery = session.createQuery(query);
dBquery.setParameter(0, fUsername);//set username variable
dBquery.setParameter(1, fPassword);//set password variable
To get the nbr of result you can just call Query::list()
int count = dBquery.list().size();
Or just :
return dBquery.list().size() == 1;
The real problem in your query is that the String should be between two quotes (but i don't advice with solution)
fusername='" + fUsername + "'
//--------^_________________^
Note: Your query is not a JPQL Query, it seems a native query, if that you have to use session.createNativeQuery(query);.
How can return correctly this query with hibernate?
Help me please
#Override
public UsuarioValido validarUserLoggin(String loggin, BigDecimal canal) throws Exception{
Query q = sessionFactory.getCurrentSession().createSQLQuery("SELECT A.ID_USER, '' AS nombre_canal_canales, A.CANAL_ID, '' AS nombre_pto_vta_puntos_de_venta, "
+ " A.PUNTO_VTA_ID, A.LOGGIN, A.PASSWORD, A.NOMBRES, A.APELLIDOS, A.SN_CAMBIO_PASS, A.ULTINGRESO, A.ULTCMBCONT, A.ESTADO, A.CONTINTENTOS, "
+ " B.NU_INT_PER AS NRO_INT_PASS, A.EMAIL, B.NDIASINACT AS DIAS_VENC_CLAV "
+ " FROM "+General.Esquema_DB+".SEG_USER A "
+ " LEFT JOIN "+General.Esquema_DB+".SEGPOLSEG B ON A.ID_USER = B.ID "
+ " WHERE A.LOGGIN = '"+loggin+"' AND A.CANAL_ID = "+canal);
List rs = q.list();
List<UsuarioValido> validos = q.list();
for (UsuarioValido usuarioValido : validos) {
System.out.println(usuarioValido.toString());
}
UsuarioValido max = (UsuarioValido)rs.get(0);
return max;
}
I usually do it here:
List<UsuarioValido> rs = q.list();
I think this is the best way to do it and not error prone. But do make sure that the query you are using sends back only that class and not a field of that class or results obtained from count(), avg() etc.
But since you are fetching fields you won't be able to use that.
In Hibernate it is recommended to bring back the results in form of List of particular classes and not use Select ...
This is my entity class.
#NamedQueries({ #NamedQuery(name = UsersEntity.NAMED_QUERY_SELECT_ALL_BY_MANAGER_ROLE,
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = '" +
UsersVO.USER_ROLE + "'") })
#Column(name = "USER_ROLE", nullable = false, length = 30)
private String userRole;
public static final String FIELD_NAME_USER_ROLE = "userRole";
This is the java class from where i execute query
#GET
#Path("/userrole")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public UsersListVO getUsers(#QueryParam("userRole") String userRole) {
// public UsersListVO getUsers(){
System.out.println(">>>>>here");
UsersListVO usersListVO = new UsersListVO();
try {
List<UsersEntity> usersEntityList = em.createNamedQuery(UsersEntity.NAMED_QUERY_SELECT_ALL_BY_MANAGER_ROLE, UsersEntity.class).setParameter(UsersEntity.FIELD_NAME_USER_ROLE, userRole).getResultList();
The test case is :-
#Test
public void testGetUsers() {
System.out.println("Start test ");
UsersListVO usersListVO = baseWebTarget.path("userrole").queryParam("userRole", "AppSystemManagerUserRole").request(MediaType.APPLICATION_JSON).get(UsersListVO.class);
if (usersListVO.getStatusType().equals(StatusTypeVO.FAILURE)) {
Assert.fail(usersListVO.getMessage());
} else {
System.out.println(usersListVO.getMessage());
}
}
I want to fetch all the managers whose roles are managerRole from users table.But got error while executing the test case in to my jdeveloper. The error i got is
java.lang.AssertionError: You have attempted to set a parameter value
using a name of userRole that does not exist in the query string
SELECT e FROM UsersEntity e WHERE e.userRole =
'AppSystemManagerUserRole'.
The error
java.lang.AssertionError: You have attempted to set a parameter value using a name of userRole that does not exist in the query string SELECT e FROM UsersEntity e WHERE e.userRole = 'AppSystemManagerUserRole' is indicating the you are trying to set a parameter that doesn't exist in your named query.
Your named query:
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = '" + UsersVO.USER_ROLE + "'"
after string concatenation results in:
query = "SELECT e FROM UsersEntity e WHERE e.userRole = 'AppSystemManagerUserRole'"
As you can see there is not named parameter that you can set. And when you tried calling setParameter(UsersEntity.FIELD_NAME_USER_ROLE, userRole) it threw the exception.
You need to introduce named parameter as below in your named query that you allows you to set later in your code.
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = :" + UsersEntity.FIELD_NAME_USER_ROLE
would result in the
query = "SELECT e FROM UsersEntity e WHERE e.userRole = :userRole"
With this you should be able to set the parameter and should work.
When I use Hibernate query language, how can I add dinamically the object I want to get from the DB?
What I want to reach is somethin like this:
......
if(....){
queryString = "from '" + Object1+ "'";
}
if(...){
queryString = "from '" + Object2+ "'";
}
....
Session session = this.getSessionFactory().getCurrentSession();
Query query = session.createQuery(queryString);
......
I tried different kind of syntax but I get errors every time.
Via Criteria API you can easily build dynamic query's...
Criteria criteria = session.createCriteria(Sale.class);
if (startDate != null) {
criteria.add(Expression.ge("date",startDate);
}
if (endDate != null) {
criteria.add(Expression.le("date",endDate);
}
List results = criteria.list();
you can use this:
......
if(....){
queryString = "from '" + Object1.getClass().getName()+ "'";
}
if(...){
queryString = "from '" + Object2.getClass().getName()+ "'";
}
....
Session session = this.getSessionFactory().getCurrentSession();
Query query = session.createQuery(queryString);
......
What actually you need is to pass class name. You can use following way to get class name of a given object.
object1.getClass().getSimpleName()
So in your case you can append this in your query
example :
if(....){
queryString = "from '" + Object1.getClass().getSimpleName()+ "'";
}