Not able to save a model record with auto generated ID - sql

I tried to save a new row to DB like this
#SuppressWarnings("unchecked")
#Modifying
public SMSIncoming save(#Param("smsIncoming") SMSIncoming smsIncoming);
here I am not setting Id as its like below:-
SMSIncoming smsIncoming = new SMSIncoming();
smsIncoming.setSender("6476963460");
smsIncoming.setReceiver("6475603720");
smsIncoming.setMsg("Testing Incoming messages");
#Id
#GeneratedValue
private Long id;
It should be auto generated while saving it thru
#SuppressWarnings("unchecked")
#Modifying
public SMSIncoming save(#Param("smsIncoming") SMSIncoming smsIncoming);
JpaRepository<SMSIncoming, Long>
but here also I am getting a lot of exceptions, I tried all options (AUTO, TABLE, SEQUENCE and IDENTITY) not able to get thru, so next I thought to get the max id from table and save by increment it. In this approach as well I am facing issues.
Issue traces while saving with IDENTITY keyword in id :-
`2019-03-26 11:32:15.347 INFO 5828 --- [ main]
c.a.s.service.SmsPluginApplicationTests : --Application Started--
smsrec.toString():::::::com.avaal.sms.model.SMSIncoming#4c6bba7d
Hibernate: insert into dbo.ozekimessagein (id, msg, msgtype, operator,
receivedtime, receiver, reference, sender, senttime) values (null, ?, ?,
?, ?, ?, ?, ?, ?)
2019-03-26 11:32:16.029 WARN 5828 --- [ main]
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 339, SQLState: S0001
2019-03-26 11:32:16.029 ERROR 5828 --- [ main]
o.h.engine.jdbc.spi.SqlExceptionHelper : DEFAULT or NULL are not allowed
as explicit identity values.
Inside test catch block::::::::::
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not execute statement; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:279)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
Issue traces while saving with SEQUENCE or AUTO keyword in id :-
`#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE/AUTO)
private long id;`
smsrec.toString():::::::com.avaal.sms.model.SMSIncoming#5d717f19
Hibernate: call next value for hibernate_sequence
2019-03-26 12:29:06.493 WARN 15412 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 102, SQLState: S0001
2019-03-26 12:29:06.494 ERROR 15412 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Incorrect syntax near 'value'.
Inside test catch block::::::::::
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:279)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
Issue traces while saving with TABLE keyword in id :-
`#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;`
`smsrec.toString():::::::com.avaal.sms.model.SMSIncoming#69e2fe3b
Hibernate: select tbl.next_val from hibernate_sequences tbl where
tbl.sequence_name=? for update
2019-03-26 12:33:33.157 ERROR 15896 --- [main]
o.hibernate.id.enhanced.TableGenerator : HHH000351: Could not read or
init a hi value com.microsoft.sqlserver.jdbc.SQLServerException: Line 1: FOR UPDATE clause allowed only for DECLARE CURSOR. at
com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:259) ~[mssql-jdbc-6.4.0.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1547) ~[mssql-jdbc-6.4.0.jre8.jar:na] at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:548) ~[mssql-jdbc-6.4.0.jre8.jar:na]`

Related

Testing unique constraint in #DataJpaTest

I wrote this test to verify unique constraint on Domain.name in the database. But it doesn't work: I expect an exception to be thrown on the domainRepository.saveAndFlush(domainDuplicate) operation, but the test ends successfully.
#RunWith(SpringRunner::class)
#DataJpaTest
class DomainRepositoryTest {
#Autowired
private lateinit var util: TestEntityManager
#Autowired
private lateinit var domainRepository: DomainRepository
#Test
fun testNonUniqueDomainSave() {
// Arrange
val domain = Domain(name = "name")
util.persist(domain)
util.flush()
util.clear()
val domainDuplicate = domain.copy(id = 0L)
// Act
domainRepository.saveAndFlush(domainDuplicate)
// Exception is expected
}
}
Test log (shortened):
INFO 13522 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext#8f8717b testClass = DomainRepositoryTest,...]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager#65f36591]; rollback [true]
Hibernate: insert into domains (name, id) values (?, ?)
Hibernate: insert into domains (name, id) values (?, ?)
Hibernate: insert into domains (name, id) values (?, ?)
INFO 13522 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext#8f8717b testClass = DomainRepositoryTest, ...], attributes = map[[empty]]]
Question: How to fix this test?
Additional question: Why 3 insert operations in log?
Database: H2
It was a problem with database initialization in tests: there was no unique constraint! I assumed that Liquibase should run migrations before any tests but in fact, it was not configured to do so. By default, Hibernate DDL auto update is used to create DB schema in tests.
I can think of 2 possible solutions:
add liquibase-core jar to test classpath and configure it to run migrations
declare #UniqueConstraint on domain entity and rely on Hibernate DDL.
The reason is that saveAndFlash() is doing an update to the entity if it exists (Yes, the name of the method is confusing..)
If you want to check your case, you need to override saveAndFlash() and use EntityManager by using persist method.
Here an example of override save() method of Spring JPA:
#PersistenceContext
private EntityManager em;
#Override
#Transactional
public Domain save(Domain domain) {
if (domain.getId() == null) {
em.persist(domain);
return domain;
} else {
return em.merge(domain);
}
}

Insert into table KUDU by datastage

I am writing to enquire about a problem in my process:
I have a Kudu table and when I try to insert by datastage (11.5 or 11.7) a new row where the size is bigger than 500 characters using the Impala JDBC Driver I receive this error:
Fatal Error: The connector failed to execute the statement: INSERT INTO default.tmp_consulta_teste (idconsulta, idcliente, idinstituicao, idunidadeinst, datahoraconsulta, desccpfcnpj, idcentral, idcontrato, idusuario, valorconsulta, descretornoxml, idintegracaosistema, nomeservidor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). The reported errors are:
[SQLSTATE HY000] java.sql.SQLException: [Cloudera]ImpalaJDBCDriver Error getting the parameter data type: HIVE_PARAMETER_QUERY_DATA_TYPE_ERR_NON_SUPPORT_DATA_TYPE.
**************How can I fix it? I need to load that information. **********
I had similar problem where the error I received was :
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw
exception [Request processing failed; nested exception is
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback;
uncategorized SQLException for SQL [update service set comments =? where service_name
="Zzzzz";]; SQL state [HY000]; error code [500352]; [Simba]
[ImpalaJDBCDriver](500352) Error getting the parameter data type:
HIVE_PARAMETER_QUERY_DATA_TYPE_ERR_NON_SUPPORT_DATA_TYPE; nested exception is
java.sql.SQLException: [Simba][ImpalaJDBCDriver](500352) Error getting the parameter
data type: HIVE_PARAMETER_QUERY_DATA_TYPE_ERR_NON_SUPPORT_DATA_TYPE] with root cause
I referred to the last most answer in the below link:
https://community.cloudera.com/t5/Support-Questions/HIVE-PARAMETER-QUERY-DATA-TYPE-ERR-NON-SUPPORT-DATA-TYPE/td-p/48849
I did the following:
1.Ensure the table is a Kudu table.
Instead of jdbcTemplate.query I did jdbcTemplate.batchUpdate in order to use a
PreparedStatement , did SetObject in PreparedStatement.
jdbcTemplate.batchUpdate(UpdateComment, new BatchPreparedStatementSetter(){
#Override
public int getBatchSize() {
return 1;
}
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setObject(1, comments);
}
});

JPA 2.1 Timestamp type field for versioning and optimistic locking always throwing OptimisticLockException

Environment: JPA 2.1, EclipseLink 2.6.3, SQL Server 2016
I want to use a field of type Timestamp for versioning and optimistic. I do not have option to use numeric column for versioning. My understanding is I just need to annotate the field with #Version and that all.
Database Table: token_t
token_id int PK
token_name varchar(100)
last_updt_dtm datetime
Entity Class
#Entity
#Table(name = "token_t")
public class TokenAE {
#Id
#Column(name = "token_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int tokenId;
#Column(name = "token_name")
private String tokenName;
#Version
#Column(name = "last_updt_dtm")
private Timestamp lastUpdtDtm;
// getter/setter omitted to avoid cluttering
}
Test Method
#Test
public void optimisticLockingTest1() throws Exception {
PersistenceHelper.getEntityManager().getTransaction().begin();
TokenAE tokenAE = tokenDAO.getToken(616);
assertNotNull("tokenAE is null", tokenAE);
tokenAE.setTokenName("new token name");
PersistenceHelper.getEntityManager().merge(tokenAE);
PersistenceHelper.getEntityManager().getTransaction().commit();
}
Note - PersistenceHelper is just helper class instantiating entity manager
As you can see, I am loading TokenAE updating name and doing merge. I made sure that underlying database record is not changed. So I am expecting the merge/update should be successful but it always throws OptimisticLockException.
See the stacktrace below. I enabled JPA query/param logging and I can see the UPDATE query and bind parameters. The value of last_updt_dtm in WHERE clause [2018-07-17 22:59:48.847] matches exactly to the value in database record and this UPDATE query should return rowCount 1 and it should be successful.
I have no idea what going on here. Any help is greatly appreciated.
Exception Stacktrace
[EL Fine]: sql: 2018-07-18 23:54:13.137--ClientSession(1451516720)--Connection(1323996324)--Thread(Thread[main,5,main])--
UPDATE token_t SET token_name = ?, last_updt_dtm = ? WHERE ((token_id = ?) AND (last_updt_dtm = ?))
bind => [new token name, 2018-07-18 23:54:13.35, 616, 2018-07-17 22:59:48.847]
[EL Warning]: 2018-07-18 23:54:13.286--UnitOfWork(998015174)--Thread(Thread[main,5,main])--Local Exception Stack:
Exception [EclipseLink-5006] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.OptimisticLockException
Exception Description: The object [TokenAE [tokenId=616, tokenName=new token name, lastUpdtDtm=2018-07-18 23:54:13.35]] cannot be updated because it has changed or been deleted since it was last read.
Class> com.test.TokenAE Primary Key> 616
at org.eclipse.persistence.exceptions.OptimisticLockException.objectChangedSinceLastReadWhenUpdating(OptimisticLockException.java:144)
at org.eclipse.persistence.descriptors.VersionLockingPolicy.validateUpdate(VersionLockingPolicy.java:790)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1086)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:803)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1790)
at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:273)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:131)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4264)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commit(UnitOfWorkImpl.java:1113)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:137)
at sunlife.us.dc.bds.token.domain.TokenDAOTest.optimisticLockingTest1(TokenDAOTest.java:39)

NamedParameterJdbcTemplate with SQL Server : Incorrect syntax near '#P0'

I have the following code which runs a query against a SQL Server DB. I've read these links
http://jenikya.com/blog/2009/02/sqlexception-select-top-number.html
MS SQL Exception: Incorrect syntax near '#P0'
but i still can't see where/why i'm getting the '#P0' issue. I've wrapped the TOP parameter in brackets.
private String DEP_AMC_QUERY = "SELECT TOP(1) ((fund_amc-reinsurance_premium)/1000)
as dep_amc "+
"FROM Hedging_Staging.dbo.:table "+
"WHERE internal_fund_code_identifier=:fund "+
"AND load_id=:load_id;";
public BigDecimal getDepAmcValue(String fund,Long load_id,String table){
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(getDataSource());
//Set up parameters
MapSqlParameterSource namedParameters = new MapSqlParameterSource("fund",fund);
namedParameters.addValue("load_id",load_id);
namedParameters.addValue("table",table);
MapUtils.debugPrint(System.out,"params", namedParameters.getValues());
//Execute query
return jdbcTemplate.queryForObject(DEP_AMC_QUERY,namedParameters,BigDecimal.class);
}
The console and exception message is
13:11:12,871 INFO [ReinsuredFundAssetProcessor] looking up dep_amc value for AXX in AI_IFL_Policy table.
params =
{
table = AI_IFL_Policy java.lang.String
fund = AXX java.lang.String
load_id = 4356 java.lang.Long
}
13:11:12,909 ERROR [AbstractStep] Encountered an error executing the step
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select top(1) ((fund_amc-reinsurance_premium)/1000) as dep_amc from Hedging_Staging.dbo.? WHERE internal_fund_code_identifier=? AND load_id=?;]; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '#P0'.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:98)
Any ideas?

How to get cursor from Oracle using Groovy?

I'm using a Groovy script in Mule ESB to get output parameters from Oracle stored procedure (including cursor) and getting an exception.
Minimal example:
import groovy.sql.Sql
import oracle.jdbc.pool.OracleDataSource
import oracle.jdbc.driver.OracleTypes
def ds = new OracleDataSource()
// setting data source parameters here
def sql = new Sql(ds)
def data = []
sql.call("""declare
result_table sys_refcursor;
begin
open result_table for select 1 as a from dual;
insert into CURSOR_TEST (ID) values (1);
commit;
${Sql.resultSet OracleTypes.CURSOR} := result_table;
insert into CURSOR_TEST (ID) values (2);
commit;
end;
"""
){ table ->
throw new RuntimeException("Never getting this exception.")
table.eachRow {
data << it.toRowResult()
}
}
sql.close()
return data
Error:
Message : java.sql.SQLException: Closed Statement (javax.script.ScriptException)
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. Closed Statement(SQL Code: 17009, SQL State: + 99999) (java.sql.SQLException)
oracle.jdbc.driver.SQLStateMapping:70 (null)
2. java.sql.SQLException: Closed Statement (javax.script.ScriptException)
org.codehaus.groovy.jsr223.GroovyScriptEngineImpl:323 (http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/script/ScriptException.html)
3. java.sql.SQLException: Closed Statement (javax.script.ScriptException)
(org.mule.api.transformer.TransformerException)
org.mule.module.scripting.transformer.ScriptTransformer:39 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.sql.SQLException: Closed Statement
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Select from CURSOR_TEST returns 1 and 2.
Oracle server version: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production.
Mule version: 3.5.0.
I'm using jdbc\lib\ojdbc6.jar from oracle client version 11.1.0.7.0.
What am I doing wrong?
The following code can help you get variable of SYS_REFCURSOR from Oracle anonymous block.
We should focus on a few key details:
Class groovy.sql.Sql doesn't have corresponding OutParameter and we make it manually as CURSOR_PARAMETER and pass it to sql.call method
Consider that the block starts with {call DECLARE and ends with END } without semicolon after END. Otherwise we can get a poorly recognizable SQLException in the face.
The question marks ? inside the sqlString are places for parameter bindings. Bindings are made in the natural order. In this example:
the first ? binds with the first element in parametersList: "abc", treating the value as IN parameter ;
the second ? binds with CURSOR_PARAMETER treating the value as OUT parameter of passed type;
There is only one enter into closure after sql.call and ResultSet rs provide rows of cursor my_cur declared in anonymous block.
import groovy.sql.OutParameter
import groovy.sql.Sql
import oracle.jdbc.OracleTypes
import java.sql.ResultSet
def driver = 'oracle.jdbc.driver.OracleDriver'
def sql = Sql.newInstance('jdbc:oracle:thin:#MY-SERVER:1521:XXX', 'usr', 'psw', driver)
// special OutParameter for cursor type
OutParameter CURSOR_PARAMETER = new OutParameter() {
public int getType() {
return OracleTypes.CURSOR;
}
};
// look at some ceremonial wrappers around anonymous block
String sqlString = """{call
DECLARE
my_cur SYS_REFCURSOR;
x VARCHAR2(32767) := ?;
BEGIN
OPEN my_cur
FOR
SELECT x || level AS my_column FROM dual CONNECT BY level < 10;
? := my_cur;
END
}
""";
// the order of elements matches the order of bindings
def parametersList = ["abc", CURSOR_PARAMETER];
// rs contains the result set of cursor my_cur
sql.call(sqlString, parametersList) { ResultSet rs ->
while (rs.next()) {
println rs.getString("my_column")
}
};