org.hibernate.MappingException :No Dialect mapping for JDBC type: -9 [duplicate] - jdbc

This question already has answers here:
JPA SQL Server No Dialect mapping for JDBC type: -9
(5 answers)
Closed 3 years ago.
When I am trying to fetch the record from a table in SQLServer2008 am getting the exception called: org.hibernate.MappingException :No Dialect mapping for JDBC type: -9 why?
Although the config file is correct.

It's the problem of hibernate mapping types.
you can extends a dialect.
eg:
public class SQLServerDialectOverrider extends SQLServerDialect{
public SQLServerDialectOverrider() {
super();
registerHibernateType(Types.NVARCHAR, Hibernate.STRING.getName());
registerHibernateType(Types.LONGVARCHAR, Hibernate.TEXT.getName());
}
}
Use this class as the dialect class.

I changed the query and explicitly cast it to varchar and it worked.......
String myquery = "select cast(t2.name as varchar) column_name from sys.objects t1 inner join sys.columns t2 on t2.object_id = t1.object_id"+
" left join sys.indexes t3 on t3.object_id = t1.object_id and t3.is_unique = 1 left join sys.index_columns t4 on t4.object_id = t1.object_id and t4.index_id = t3.index_id and t4.column_id = t2.column_id where (upper(t1.type) = 'U' or upper(t1.type) = 'V') and upper(schema_name(t1.schema_id)) = 'dbo' and upper(t1.name) = 'TEST'";

This issue occurs if you are accessing the database table data in the different format on which its store in database
Example:
in data base column type is "nvarchar" and you are accessing data as a string via hibernate.
To avoid this you can add scalar in hibernate which will explicitly cast the column data as per requirement. scalar can be added in java while executing the query also in the hbm.xml file.

Related

Criteria API with ODER BY CASE expression throws SQLException: ORA-12704 "character set mismatch"

I am using criteria API to create my query. Because of special sorting algorithm I use an "order by case" expression. My Unit-Tests using in memory H2 DB and are working. In the development stage we are using Oracle DB and there I get an "SQLException: ORA-12704" when executing the query.
Assume my root entity 'Foo' has a Set of 'Bar's. Bar has an attribute 'myOrderByColumn'
public class Bar {
...
#NotBlank
#javax.validation.constraints.Size(max = 255)
#Column(name = "MYORDERBYCOL")
private java.lang.String myOrderByColumn;
...
}
Here is the code which produces the exception. It creates the Order object later used in CriteriaQuery.orderBy(..)
private Order buildOrderBy(final CriteriaBuilder cb,
final Root<Foo> rootEntity,
final List<String> somehowSpecialOrderedList) {
final Expression<String> orderByColumn =
rootEntity.join(Foo_.bars, JoinType.LEFT).get(Bars.myOrderByColumn);
CriteriaBuilder.SimpleCase<String, Integer> caseRoot = cb.selectCase(orderByColumn);
IntStream.range(0, somehowSpecialOrderedList.size())
.forEach(i -> caseRoot.when(somehowSpecialOrderedList.get(i), i));
final Expression<Integer> selectCase = caseRoot.otherwise(Integer.MAX_VALUE);
return cb.asc(selectCase);
}
I took a look into the Oracle DB. The type of the column 'myOrderByColumn' ist NVARCHAR2(255).
I guess the problem here ist that the "when" part in the SQL query must match with the type of the 'MYORDERBYCOL' database column, which is NVARCHAR2. In Java I use Strings. Probably Hibernate is not casting this correctly!?
I can produce the database ORA-12704 error by
SELECT FOO.id
FROM FOO
LEFT OUTER JOIN BAR ON FOO.id = BAR.fk_id
ORDER BY
CASE FOO.myorderbycol
WHEN '20' THEN 1
ELSE 2
END ASC;
This SQL works
SELECT FOO.id
FROM FOO
LEFT OUTER JOIN BAR ON FOO.id = BAR.fk_id
ORDER BY
CASE FOO.myorderbycol
WHEN cast('20' as NVARCHAR2(255))
THEN 1ELSE 2
END ASC;
How do I have to adjust my oder by case expression with criteria API so that the query is working with any database? (must later work with at least H2, Oracle, MS SQL, PostgreSQL)
Looks like an Oracle issue to me. Which version are you using? You can try a different approach which might work.
CriteriaBuilder.SearchedCase<Integer> caseRoot = cb.selectCase();
IntStream.range(0, somehowSpecialOrderedList.size())
.forEach(i -> caseRoot.when(cb.equal(orderByColumn, somehowSpecialOrderedList.get(i)), i));
final Expression<Integer> selectCase = caseRoot.otherwise(Integer.MAX_VALUE);

How to INNER JOIN a jsonb column with CriteriaBuilder

I've been researching a while about how can I implement an Inner Join using CriteriaBuilder, but the thing is that one of the arguments which both tables have in commons is located inside a jsonb column, so the question is:
How can I INNER JOIN 2 tables by an argument that is located inside a jsonb column called "data" with criteria?
I'll drop down the example code of what I currently have.
public final CriteriaQuery<TutenBookingMacarena> createRatedBookings(
MacarenaBookingSearchFilter filters,
Integer page,
Integer pageSize,
Security security
) {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<TutenBookingMacarena> criteria = builder.createQuery(TutenBookingMacarena.class);
final Root<TutenBookingMacarena> root_Booking = criteria.from(TutenBookingMacarena.class);
Join<TutenBookingMacarena, TutenCaseMacarena> rootJoin = root_Booking.join(String.valueOf(
builder.function("jsonb_extract_path_text",
String.class,
root_Booking.<String>get("data"),
builder.literal("caseId")
)
));
...
}
But when executing those lines of code I get an error message that says the named attribute can not be found. Any idea what's wrong here?

HANA query with dynamic placeholder executed using jdbcTemplate in Spring Boot

I have a few HANA queries that rely on PLACEHOLDER input. The input to this is currently hardcoded which is leading to SQL injection vulnerability being detected by Veracode.
In order to fix that, I am trying to parameterize the value given to PLACEHOLDER using PreparedStatement, but getting the below error :
PreparedStatementCallback; uncategorized SQLException for SQL [SELECT * FROM some_table (PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ?) WHERE some_flag = ?; ]; SQL state [HY000]; error code [2048]; SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred\n; nested exception is com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred
I have already checked this solution and gone through the documentation for input parameters in SAP HANA. Below is my code :
String sqlQuery = SELECT * FROM some_table ( PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ? ) WHERE some_flag = ? ;
PreparedStatementSetter preparedStatementSetter = (PreparedStatement ps) -> {
ps.setString(1, firstInput);
ps.setString(2, secondInput);
}
ResultSetExtractor<T> rse = new DataResultSetExtractor();
getJdbcTemplate().query(sqlQuery, preparedStatementSetter, rse);
The same works well with the hardcoded way (prone to SQL injection) :
StringBuffer sql = new StringBuffer();
sql.append("SELECT * FROM some_table ").append("( 'PLACEHOLDER' = ('$$IP_SOME_COLUMN$$',").append(firstColumnValue).append("))");
//Map<String,Object> paramMap = new HashMap<String,Object>();
//getNamedParameterJdbcTemplate().query(sql.toString(), paramMap, rse);
How do I fix this error?
Figured the issue out. It seems, in the new syntax you need to provide the input parameter in single quotes and not in triple single quotes
Works : 'foo'
Doesn't work : '''bar'''

Joins Using QueryDsl and Boolean Expression

Need a help regarding QueryDsl using BooleanExpression. Find the requirement below.
I have Enquiry and Followup table. OneToMany mapping in between them. 1 Enquiry having many followup.
Suppose i have 5 enquiries. for each enquiry i have 3 followup.
Expectation is ..i need last record of followup for each enquiry.
Please find the different ways i have tried.
QBuyerFollowUp qBuyerfollowup = QBuyerFollowUp.buyerFollowUp;
ListPath<BuyerFollowUp, QBuyerFollowUp> followUpList = qBuyerEnquiry.followUpList;
BooleanExpression expression = commonExpression.and(new JPAQuery<>().select(qBuyerfollowup.nextDate).from(qBuyerfollowup)
.where(qBuyerfollowup.eq(followUpList.any()))
.orderBy(qBuyerfollowup.followUpId.desc()).limit(1).eq(new Date());
please ignore commonExpression which is an another expression.
Error: Subquery returns more than 1 row
BooleanExpression expression = followUpList.any().followUpId.in(new JPAQuery<QBuyerFollowUp>().select(qBuyerfollowup.followUpId.max())
.from(qBuyerfollowup).groupBy(qBuyerfollowup.buyerEnquiry.id)
.having(qBuyerfollowup.nextDate.eq(dateFormat.parse(dateFormat.format(new Date())))));
Error: unknown column nextDate.
Here generated query is:
select count(buyerenqui0_.id) as col_0_0_ from buyer_enquiry buyerenqui0_ where
buyerenqui0_.assigned_to= 79 and
(buyerenqui0_.created_at between "2020-05-01 00:00:00" and "2020-05-31 23:59:59") and buyerenqui0_.enq_status<> "Dropped" and
not ( not (exists (select followupli1_.id from buyer_followup followupli1_ where buyerenqui0_.id=followupli1_.buyer_enquiry_id)))
and (exists (select 1 from buyer_followup followupli2_ where buyerenqui0_.id=followupli2_.buyer_enquiry_id and
(followupli2_.id in (select max(a.id) from buyer_followup a group by a.buyer_enquiry_id having date(a.next_date)=date(now())))));
solution: If will remove alias name 'a' from this query
select max(a.id) from buyer_followup a group by a.buyer_enquiry_id having date(a.next_date)=date(now())))
it is working fine.
But we don't have any control on this because alias name is generated by Spring.
You can't join subqueries in JPQL, but you can project them, which should be sufficient in this case:
QInquiry inquiry = QInquiry.inquiry;
QFollowup followup = QFollowup.followup;
Map<Inquiry, Followup> results = query().from(inquiry)
.transform(GroupBy.groupBy(inquiry).as(query().from(followup)
.where(followup.inquiry.eq(inquiry)
.orderBy(followup.id.desc())
.limit(1)))

calling derby (java db) 'show tables' from jdbc

I need to enumerate the tables in a Derby (aka Java DB) database using JDBC in a Java program. All I am aware of for doing this is the SHOW TABLES command.
I first tried with something similar to this...
String strConnectionURL = "jdbc:derby:/path/to/derby/database;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
Statement statement = connection.createStatement();
boolean boResult = statement.execute("SHOW TABLES");
if (boResult) {
System.out.println("yay!");
}
...but that throws an exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So next I thought maybe I needed to use a CallableStatement so I tried this...
String strConnectionURL = "jdbc:derby:/path/to/derby/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
CallableStatement statement = connection.prepareCall("SHOW TABLES");
boolean boResult = statement.execute();
if (boResult) {
System.out.println("yippee!");
}
...but that throws the same exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So, can anyone help me enumerate the tables in my Derby (Java DB) database from JDBC?
EDIT: I'm looking around and starting to get a feeling this may be a general JDBC question. In other words, one could/would enumerate all a db's tables with the DatabaseMetaData object that can be retrieved from the Connection object. Looking into that (and looking forward to responses)...
EDIT 2: I found a pure JDBC solution, but am still happy to hear alternatives...
String strConnectionURL = "jdbc:derby:/path/to/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet resultSet = dbmd.getTables(null, null, null, null);
while (resultSet.next()) {
String strTableName = resultSet.getString("TABLE_NAME");
System.out.println("TABLE_NAME is " + strTableName);
}
Show Tables is an ij command, not a base SQL statement, so you can't directly execute it. As you noted in your "EDIT 2", you can use the DatabaseMetaData to do this. Two other ways to do it are: you can select from the system catalogs (see http://db.apache.org/derby/docs/10.8/ref/rrefsistabs24269.html) , or you can use the "ij.runScript" method to run the ij tool from within your program, and pass it the "show tables" command (see http://db.apache.org/derby/docs/10.8/publishedapi/jdbc3/org/apache/derby/tools/ij.html)
As Bryan suggested ij.runScript - the code would look like this:
public void showTbls() throws Exception{
String sqlIn = "SHOW TABLES;";
InputStream stream = new ByteArrayInputStream(sqlIn.getBytes(StandardCharsets.UTF_8));
ij.runScript(conn,stream,StandardCharsets.UTF_8.name(), System.out,"UTF-8");
stream.close();
}
assumming conn is a opened derby Connection
But the disadvantage is that you are getting only string output. Not an ResultSet as you would get from:
Statement stmt = conn.createStatement();
ResultSet results = stmt.executeQuery("SELECT * FROM sys.systables");
or if you want only user table names you can use following SQL:
ResultSet results = stmt.executeQuery("SELECT TABLENAME FROM SYS.SYSTABLES WHERE TABLETYPE='T'");
A very similar output to
SHOW TABLES;
can be produced by using the following jdbc compliant query:
SELECT TABLENAME, (SELECT SCHEMANAME
FROM SYS.SYSSCHEMAS
WHERE SYS.SYSTABLES.SCHEMAID = SYS.SYSSCHEMAS.SCHEMAID)
AS SCHEMANAME
FROM SYS.SYSTABLES WHERE TABLETYPE='T'
It also shows you the probably useful SCHEMA information for each TABLE entry. Skip
TABLETYPE='T'
if you also want to see the system tables of your database as the user before has mentioned already.

Resources