SQL UNINITIALIZED Error when Executing a SQL Builder Class - MyBatis Springboot - spring-boot

I have created an SQL statement using myBatis SQL builder, but I am to finding documentation on how to execute the string once its created. Currently, I have the following:
CONTROLLER:
#GetMapping("/simpleQuery/{schema}/{fromTable}")
public List <Object> getAllDataFromTable (#PathVariable String schema, #PathVariable String fromTable){
//return queryMapper.getSimpleQueryResults(schema, fromTable);
return queryService.selectDataFromTable(schema, fromTable);
}
SERVICE - where SQL string gets built
public List<Object> selectDataFromTable(String schema, String fromTable){
String selectDataFromTable = new SQL(){{
SELECT ("*");
FROM (schema + "." + fromTable);
}}.toString();
return queryMapper.getSimpleQueryResults(selectDataFromTable);
}
System.out.println(selectDataFromTable);
I've printed the SQL string out to the console and it looks like this:
SELECT *
FROM DB.SOMETABLENAME
UPDATE: I have also tried building the sql string like:
String selectDataFromTable = "SELECT * FROM " + schema +"." + fromTable;
So that the query is all one line but I still get the same results/error
MAPPER - sql string gets exectued
#Select("#{sql}")
List <Object> getSimpleQueryResults(String sql);
The query get executed but an error returns:
Invalid SQL type: sqlKind = UNINITIALIZED
So how do I get the SQL string to execute using mybatis in Springboot.
NOTE - I'm using annotation not XML.
Thank you

Related

How can a result of a query be returned as JSON? Spring Boot

I have a method that should output me a JSON from a desired table. To keep the service as flexible as possible, I decided to use native queries, not to use entities and also to work without repositories. But so that I don't just get a list of objects from the database like this statement "final String sql = "SELECT * FROM " + schemaName + "." + tableName;", I extended my SQL statement with array_to_json. This is how I get a JSON from my DB.
Here is my method:
#Override
public List<Map<String, Object>> getList(String tableName, String schemaName) {
// final String sql = "SELECT * FROM " + schemaName + "." + tableName;
final String sql = "SELECT array_to_json(array_agg(" + tableName + ")) FROM " + schemaName + "." + tableName;
final Query query = em.createNativeQuery(sql);
final List<Map<String, Object>> queryResult = query.;
return queryResult;
}
When I execute my sql statement in the PG Admin then I get the following JSON:
[{"id":1,"analytic_id":1,"propertytype":"shape","min_val":null,"max_val":null,"string_val":"102941","case_else":0,"result":"kugel"},{"id":2,"analytic_id":1,"propertytype":"shape","min_val":null,"max_val":null,"string_val":"019283","case_else":0,"result":"rechteck"},{"id":3,"analytic_id":1,"propertytype":"shape","min_val":null,"max_val":null,"string_val":"0122343","case_else":0,"result":"prism"},{"id":6,"analytic_id":1,"propertytype":"color","min_val":0,"max_val":20,"string_val":null,"case_else":0,"result":"grun"},{"id":7,"analytic_id":1,"propertytype":"color","min_val":21,"max_val":50,"string_val":null,"case_else":0,"result":"gelb"},{"id":8,"analytic_id":1,"propertytype":"color","min_val":51,"max_val":80,"string_val":null,"case_else":0,"result":"hellblau"},{"id":9,"analytic_id":1,"propertytype":"color","min_val":81,"max_val":999,"string_val":null,"case_else":0,"result":"rot"},{"id":10,"analytic_id":1,"propertytype":"color","min_val":null,"max_val":null,"string_val":null,"case_else":1,"result":"lila"}]
Now for my question:
So I get a JSON from my query. But how do I rebuild my method so that I can display the result of my query in the GetRequest. It is important to me that I get a JSON with all data back and that the return type is compatible with OPENAPI 3.0.
Thanks in advance

Is there a better way to execute this SQL statement in Spring using JdbcTemplate?

I have an SQL statement to select a BRAND_NAME based on an input parameter. The code goes something like this:
public ResponseEntity<List<Map<String, Object>>> getBrand(String brandName){
sql = "SELECT BRAND_NAME AS \"brandName\" FROM BRAND_E WHERE LOWER(BRAND_NAME) LIKE '%" + brandName + "%'";
return new ResponseEntity<List<Map<String, Object>>>(jdbc.queryForList(sql), HttpStatus.OK);
}
I've found out that this can probably cause SQL injection attacks, so I was wondering how to code this better.
Yes.If you directly use the request param on your sql it can lead to SQL injection attacks. We can always go with the prepared statement by adding a placeholder to where the values must be added.
Use queryForList(String sql, Object... args) or queryForList(String sql, Object[] args, Class<T> elementType)
Eg:-
String employeeId= "1";
String sql = "select id,name,address from employee where id = ?";
getJdbcTemplate(). queryForList(sql, new Object[]{employeeId}, Employee.class);

Problem in updating a data column in spring

I have a Database table called ProgramData. their i have a data column called Id and executed. id set to be as auto increment.
Table structure is like this.
What i want is according to id executed column need to be updated. following is my code segment.
public void saveDtvProgDataExecuted()
{
ProgramData programeData = new ProgramData();
String SQL = "UPDATE program_data SET executed=1 WHERE programeData.id = ?";
this.jdbcTemplate.update(SQL);
}
If i run this code this gives me error like bad SQL grammar [UPDATE program_data SET executed=1 WHERE programeData.id = ?]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1
Problem is you’re not passing the ID value to the jdbctemplate.
You should use
this.jdbctemplate.update(SQL, id);
Where id is the id of the record you’re updating.
Please refer to the documentation for more information:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#jdbc-updates
TRY THIS statement while you are passing ? in your sql query it need to be set while execution.
String SQL = "UPDATE program_data SET executed=1 WHERE programeData.id = ?";
this.jdbcTemplate.update(SQL,new PreparedStatementCallback<Boolean>(){
#Override
public Boolean doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
ps.setInt(1,"here you need to pass value of programeData.id);
return ps.execute();
}
});

JPA - How to select from a database function?

I have the following SQL query in T-SQL:
SELECT a.ReportDate,
a.Value,
a.Quantity,
a.ID,
a.Code
FROM AQF.fCalc(#data) a
#data is a varbinary. I'm trying to replicate this query using JPA. (I'm actually using Spring Data JPA 1.10.2.) I have the following defined in MyRepository:
#Query("SELECT a "
+ "FROM function('AQF.fCalc', :data) a "
)
List<MyClass> getCalcData(#Param("data") byte[] data);
MyClass is as follows:
#Entity
#Data // using lombok to create setters, getters, etc.
public class MyClass {
#Id
private Long id;
private Date reportDate;
private BigDecimal value;
private BigDecimal quantity;
private String code;
}
When I call getCalcData, I receive the following error:
antlr.NoViableAltException: unexpected token: function
at org.hibernate.hql.internal.antlr.HqlBaseParser.fromRange(HqlBaseParser.java:1501) [hibernate-core-5.0.9.Final.jar:5.0.9.Final]...
How can I call the function AQF.fCalc (and pass in the byte array) using JPA?
Update 1
I've now tried using a native query too, but now I get an error stating:
java.sql.SQLException: An error occurred while getting new row from user defined Table Valued Function :
System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: Data, Report. Line 24, position 804.
Here's the test code for the native query in MyRepository:
#Query(value = "SELECT a.code "
+ "FROM AQF.fCalc(?1) a",
nativeQuery = true)
List<String> getCalcData(byte[] data);
Update 2
I was able to resolve the error noted in "Update 1" above. The byte array of data in the getCalcData was corrupted. Once I resolved that issue, the error no longer appeared. So, now I can run as a native query. However, I would still like to know how to use JPQL to make this function call.
You can use StoredProcedureQuery. From the javadoc
Interface used to control stored procedure query execution.
Refer this sample code.
Assume your SQL function name is sales_tax in this example.
EntityManager em = factory.createEntityManager();
// Create call stored procedure
em.getTransaction().begin();
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("sales_tax");
// set parameters
storedProcedure.registerStoredProcedureParameter("subtotal", Double.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("tax", Double.class, ParameterMode.OUT);
storedProcedure.setParameter("subtotal", 1f);
// execute SP
storedProcedure.execute();
// get result
Double tax = (Double)storedProcedure.getOutputParameterValue("tax");
System.out.println("Tax is: " + tax);
em.getTransaction().commit();
em.close();

How to use prepared statement that returns resultset with jdbcTemplate in spring mvc 3?

Here is my code which uses jdbcTemplate
String SQL = "select branch from branchTable where branch_name = '" + branch + "'";
ArrayList<String> branchList = (ArrayList<String>) jdbcTemplateObject.query(SQL, new RowMapper() {
public Object mapRow(ResultSet resultSet, int i) throws SQLException {
return resultSet.getString("city_desc");
}
});
return branchList;
Now i want to be able to use preparedstatement with a query like "select branch from branchTable where branch_name = ?"
How can i do that with jdbcTemplate ?
Examples i searched show demonstration on how to use it with update or insert query, but not with select query..
Please help.
JdbcTemplate has another query() method which takes arguments of the prepared statement as parameter:
jdbcTemplateObject.query(SQL, new Object[] {branchName}, new RowMapper() {...});
Note that:
SQL should be named sql
You should use List and not ArrayList. Nothing in the javadoc guarantees that an ArrayList is returned. And you shouldn't care about the concrete type of list returned.
You should use a RowMapper<String> and not a raw RowMapper.

Resources