jdbcType=BIGDECIMAL not supported in mybatis and ibatis - jdbc

Using jdbcType=BIGDECIMAL is not supported in myBatis and ibatis and is throwing the next error:
Error resolving JdbcType. Cause: java.lang.IllegalArgumentException:
No enum constant org.apache.ibatis.type.JdbcType.BIGDECIMAL
What is the jdbcType alternative instead of BIGDECIMAL?
I'm using mybatis-3.4.4 version

That's happen because BIGDECIMAL jdbc type doesn't exist. Just take a look the enum JdbcType of org.apache.ibatis.type.
You should use DECIMAL.
The list of JdbcTypes available in JdbcType enum:
ARRAY(2003),
BIT(-7),
TINYINT(-6),
SMALLINT(5),
INTEGER(4),
BIGINT(-5),
FLOAT(6),
REAL(7),
DOUBLE(8),
NUMERIC(2),
DECIMAL(3),
CHAR(1),
VARCHAR(12),
LONGVARCHAR(-1),
DATE(91),
TIME(92),
TIMESTAMP(93),
BINARY(-2),
VARBINARY(-3),
LONGVARBINARY(-4),
NULL(0),
OTHER(1111),
BLOB(2004),
CLOB(2005),
BOOLEAN(16),
CURSOR(-10),
UNDEFINED(-2147482648),
NVARCHAR(-9),
NCHAR(-15),
NCLOB(2011),
STRUCT(2002),
JAVA_OBJECT(2000),
DISTINCT(2001),
REF(2006),
DATALINK(70),
ROWID(-8),
LONGNVARCHAR(-16),
SQLXML(2009),
DATETIMEOFFSET(-155);

By using below type handler I have resolved my same issue:
<insert id=".......">
INSERT INTO demo (number_of_cities)
VALUES( #{numberOfCities, typeHandler=org.apache.ibatis.type.BigDecimalTypeHandler});
</insert>

Related

SpringBootTest in error with h2 v2.1.214 because of PageRequest

I have some tests in error after upgrading from Spring boot 2.5.6 to 2.7.3.
For information we use Oracle for the database and h2 for tests.
I have some tests in failure with the following error:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException
In fact, the version of h2 was 1.4.200 before and is 2.1.214 now and a lot of things seem to have changed. The reason of the error is not always the same according to the test in error. Sometimes it is an error with a table not found (not solved yet), sometimes it is an error with "Values of types "BOOLEAN" and "INTEGER" are not comparable" (solved by updating a query where a comparison was done with a boolean column like this myBoolean = 0 and it has been updated to myBoolean = false) and I also have an error on a query done with a PageRequest.
For this last case, I have a Controller like this:
public Page<MyEntity> doSomething() {
final Sort sort = Sort.by(Order.desc("column1"));
final PageRequest pageRequest = PageRequest.of(0, 1000, sort);
return myEntityRepository.findAll(pageRequest);
}
But I have an error like that:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "select myentity0_.id as id1_47_, myentity0_.column1 as column1_47_, myentity0_.column2 as column2_47_ from my_table myentity0_ order by myentity0_.column1 desc [*]limit ?"; SQL statement:
select myentity0_.id as id1_47_, myentity0_.column1 as column1_47_, myentity0_.column2 as column2_47_ from my_table myentity0_ order by myentity0_.column1 desc limit ? [42000-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:502)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:223)
at org.h2.message.DbException.get(DbException.java:199)
at org.h2.message.DbException.getSyntaxError(DbException.java:247)
at org.h2.command.Parser.getSyntaxError(Parser.java:898)
at org.h2.command.Parser.prepareCommand(Parser.java:572)
at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631)
at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:92)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:337)
at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:149)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:176)
... 205 more
If I change the Controller like this,the test is in success:
public Page<MyEntity> doSomething() {
List<MyEntity> result = myEntityRepository.findAll();
return new PageImpl<MyEntity>(result);
}
So It seems that the problem was due by the use of PageRequest.
Do you have an idea please?
Java persistence libraries are usually tested only with default Regular mode of H2 and may not work well with other modes.
Oracle doesn't support MySQL/PostgreSQL-style LIMIT, and H2 doesn't allow it in Oracle compatibility mode, but some libraries produce LIMIT instead of standard OFFSET / FETCH for H2.
Spring Data JDBC (spring-data-relational) added support of custom compatibility modes of H2 only about a month ago and version 2.4.3 with this fix isn't released yet.
Hibernate ORM 6.*.* should work well, but Hibernate ORM 5.6.* has a known issue:
https://hibernate.atlassian.net/jira/software/c/projects/HHH/issues/HHH-15318
You can enable LIMIT in Oracle compatibility mode of H2 as a temporary workaround. To do that, you need to execute the following Java code during initialization of your application:
org.h2.engine.Mode mode = org.h2.engine.Mode.getInstance("ORACLE");
mode.limit = true;

How to migrate <dynamic> from ibatis to mybatis

I wish to change this from ibatis 2.0
UPDATE AccountData SET
StatisticAccountingUnits= <isNotNull property="statisticAccountingUnits">#statisticAccountingUnits#</isNotNull> <isNull property="statisticAccountingUnits">null</isNull>,
TotalStatisticDays= <isNotNull property="totalStatisticDays">#totalStatisticDays#</isNotNull> <isNull property="totalStatisticDays">null</isNull>,
<dynamic>
<isNotNull property="unitPrice" prepend=", ">UnitPrice = #unitPrice#</isNotNull>
<isNotNull property="settlementAnnexNumber" prepend=", ">SettlementAnnexNumber = #settlementAnnexNumber#</isNotNull>
</dynamic>
WHERE AccountDataID=#accountDataId#
to Mybatis version 3.2.7
You can look here - http://mybatis.github.io/mybatis-3/dynamic-sql.html
By the way, you don't need code like
<isNotNull property="statisticAccountingUnits">#statisticAccountingUnits#</isNotNull> <isNull property="statisticAccountingUnits">null</isNull>
use #{statisticAccountingUnits, jdbcType=NUMERIC}
http://mybatis.github.io/mybatis-3/sqlmap-xml.html#Parameters
The JDBC Type is required by JDBC for all nullable columns, if null is
passed as a value. You can investigate this yourself by reading the
JavaDocs for the PreparedStatement.setNull() method.

How is a Log4j2 JDBCAppender used to insert into a date column?

I am trying to use Log4j2's JDBCAppender to insert a value into an Oracle date column. I know how to use isEventTimestamp, but I need to insert a date from the ThreadContext.
I'm guessing I'm not formatting the date correctly, but I can't find any documentation on how to correctly format.
How I'm formatting Date:
ThreadContext.put("DATE_VALUE", new Date().toString());
This is the Log4j2 JDBCAppender Column element I'm using:
<Column name="DATE_COLUMN" pattern="%X{DATE_VALUE}" />
This is the error I'm getting:
2013-07-25 08:17:18,145 ERROR Failed to insert record for log event in
manager [jdbcManager{ description=XXXXXXXXX, bufferSize=5,
connectionSource=driverManager{ url=jdbc:oracle:thin:#//XXXXXXXXX,
username=XXXXXXXXX, passwordHash=XXXXXXXXX }, tableName=XXXXXXXXX,
columns=[ { name=DATE_COLUMN, layout=%X{DATE_VALUE}, literal=null,
timestamp=false } ] }]. java.sql.SQLDataException:
ORA-01858: a non-numeric character was found where a numeric was expected
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
Any Suggestions?

Errors when creating table using cassandra-jdbc-1.2.1 jar

I am having some difficulty creating a column family (table) in cassandra via the cassandra-jdbc driver.
The cql command works correctly in cqlsh, but doesn't when using cassandra jdbc. I suspect this is something to do with the way I have defined my connection string. Any help would be greatly helpful.
Let me try and explain what I have done.
I have created a keyspace using cqlsh with the following command
CREATE KEYSPACE authdb WITH
REPLICATION = {
'class' : 'SimpleStrategy',
'replication_factor' : 1
};
This is as per the documentation at: http://www.datastax.com/docs/1.2/cql_cli/cql/CREATE_KEYSPACE#cql-create-keyspace
I am able to create a table (column family) in cqlsh using
CREATE TABLE authdb.users(
user_name varchar PRIMARY KEY,
password varchar,
gender varchar,
session_token varchar,
birth_year bigint
);
This works correctly.
My problems start when I try to create the table using cassandra-jdbc-1.2.1.jar
The code I use is:
public static void createColumnFamily() {
try {
Class.forName("org.apache.cassandra.cql.jdbc.CassandraDriver");
Connection con = DriverManager.getConnection("jdbc:cassandra://localhost:9160/authdb?version=3.0.0");
String qry = "CREATE TABLE authdb.users(" +
"user_name varchar PRIMARY KEY," +
"password varchar," +
"gender varchar," +
"session_token varchar," +
"birth_year bigint" +
")";
Statement smt = con.createStatement();
smt.executeUpdate(qry);
con.close();
} catch (Exception e) {
e.printStackTrace();
}
When using cassandra-jdbc-1.2.1.jar I get the following error:
main DEBUG jdbc.CassandraDriver - Final Properties to Connection: {cqlVersion=3.0.0, portNumber=9160, databaseName=authdb, serverName=localhost}
main DEBUG jdbc.CassandraConnection - Connected to localhost:9160 in Cluster 'authdb' using Keyspace 'Test Cluster' and CQL version '3.0.0'
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.cassandra.thrift.Cassandra$Client.execute_cql3_query(Ljava/nio/ByteBuffer;Lorg/apache/cassandra/thrift/Compression;Lorg/apache/cassandra/thrift/ConsistencyLevel;)Lorg/apache/cassandra/thrift/CqlResult;
at org.apache.cassandra.cql.jdbc.CassandraConnection.execute(CassandraConnection.java:447)
Note: the cluster and key space are not correct
When using cassandra-jdbc-1.1.2.jar I get the following error:
main DEBUG jdbc.CassandraDriver - Final Properties to Connection: {cqlVersion=3.0.0, portNumber=9160, databaseName=authdb, serverName=localhost}
main INFO jdbc.CassandraConnection - Connected to localhost:9160 using Keyspace authdb and CQL version 3.0.0
java.sql.SQLSyntaxErrorException: Cannot execute/prepare CQL2 statement since the CQL has been set to CQL3(This might mean your client hasn't been upgraded correctly to use the new CQL3 methods introduced in Cassandra 1.2+).
Note: in this instance the cluster and keyspace appear to be correct.
The error when using the 1.2.1 jar is because you have an old version of the cassandra-thrift jar. You need to keep that in sync with the cassandra-jdbc version. The cassandra-thrift jar is in the lib directory of the binary download.

Spring JDBC lob insertion fails: Invalid column type

The code:
jdbcTemplate.update("MERGE INTO app_role_data x USING (select ? name, ? xml FROM dual) d ON (x.app_name = d.name) WHEN MATCHED THEN UPDATE SET x.xml_blob = d.xml WHEN NOT MATCHED THEN INSERT(app_name, xml_blob) VALUES(d.name, d.xml)",
new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {
ps.setString(1, appName);
lobCreator.setClobAsString(ps, 2, xmlBlob);
}
});
lobHandler is an instance of OracleLobHandler that's injected in the context.
The exception:
Caused by: java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:9231)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8812)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9534)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:9517)
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:351)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:216)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.doSetValue(ArgPreparedStatementSetter.java:65)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.setValues(ArgPreparedStatementSetter.java:46)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:815)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:1)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
This is Spring framework 3.0.5.RELEASE.
Our oracle driver dependency is
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.3.0</version>
</dependency>
The table:
SQL> desc app_role_data
Name Null? Type
----------------------------------------- -------- ----------------------------
APP_NAME VARCHAR2(64)
XML_BLOB CLOB
I'm not even sure what other information I can add, but I'll be happy to do so if I've left something out.
Turns out, execute() takes a PreparedStatementCallback, while update() takes a PreparedStatementSetter. But both have overloads that take Object, so the compiler doesn't complain.
Grumble. That's a day of my life I'll never get back.
I am being a little skeptical about the column names here
Can you try something like below in your MERGE
select ? as name, ? as xml FROM dual
But I am skeptical of that too since the way you can have dynamic column names is by creating a dynamic sql and executing it with EXECUTE IMMEDIATE.
Or may be something like this (not best in terms of Oracle)-
jdbcTemplate.update("MERGE INTO app_role_data x USING dual d ON (x.app_name = ?) WHEN MATCHED THEN UPDATE SET x.xml_blob = ? WHEN NOT MATCHED THEN INSERT(app_name, xml_blob) VALUES(?, ?)",......

Resources