java.sql.SQLException: ORA-01002: fetch out of sequence on XATransaction - oracle

On the same data sometimes throws the exception java.sql.SQLException: ORA-01002: fetch out of sequence, but in most attempts all working fine.
Java app running on Glassfish 3.1.2.2. Can anybody explain me, where is the problem?
#Singleton
#LocalBean
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class MarketCodesSingleton {
#Resource(mappedName="jdbc/sss")
private DataSource source;
private volatile static Map<Interval, String> marketCodes;
#PostConstruct
#Schedule(minute="*/10", hour="*")
public void fillMarketCodes() {
try(Connection conn = source.getConnection()) {
Map<Interval, String> marketCodesInt = new TreeMap<>();
DaoFactory.getMarketCodesDao().fillMarketCodes(marketCodesInt, conn);
marketCodes = Collections.unmodifiableMap(marketCodesInt);
Logger.getLogger(getClass().getName()).log(Level.FINE, "MarketCodes updated");
} catch (SQLException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "fillMarketCodes exception",e);
throw new EJBException("fillMarketCodes exception",e);
}
}
public String getMarketCode(Long msisdn) {
Interval interval = new Interval(msisdn);
return marketCodes.get(interval);
}
}
DaoFactory.getMarketCodesDao().fillMarketCodes:
private static final String getMarketCodes_SQL = "CALL SERVICE_PKG.GET_MARKET_CODES(?)";
#Override
public void fillMarketCodes(Map<Interval, String> intervals, Connection conn) throws SQLException {
try (CallableStatement cs = conn.prepareCall(getMarketCodes_SQL)) {
//-10 is a OracleTypes.CURSOR
cs.registerOutParameter(1, -10);
cs.execute();
try (ResultSet rs = (ResultSet) cs.getObject(1)) {
//*******Exception throws on the rs.next() in this method*******
while (rs.next()) {
Interval interval = new Interval(rs.getLong("from_no"), rs.getLong("to_no"));
intervals.put(interval, rs.getString("market_code"));
}
}
}
}
Procedure:
procedure GET_MARKET_CODES(
c_cursor OUT SYS_REFCURSOR
) AS
BEGIN
OPEN c_cursor FOR
SELECT from_no, to_no, market_code
FROM market_codes;
END GET_MARKET_CODES;
Connection properties:
<jdbc-connection-pool
connection-creation-retry-interval-in-seconds="5"
datasource-classname="oracle.jdbc.xa.client.OracleXADataSource"
max-pool-size="200"
max-connection-usage-count="1000"
res-type="javax.sql.XADataSource"
steady-pool-size="0"
name="sss_pool"
connection-creation-retry-attempts="5">
<property name="URL" value="jdbc:oracle:thin:#(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = xx)))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = xx)))"></property>
<property name="Password" value="***"></property>
<property name="User" value="***"></property>
</jdbc-connection-pool>

The code is incomplete, so I can only guess:
the cursor was closed and you tried to fetch again
you did select for update and committed and then tried to fetch the next row.

Is your connection set to auto commit? A fetch across a commit or rollback is likely to cause this exception.
I also noticed that your SQL isn't surrounded by begin/end as in the Oracle docs or {} as in this example and the Oracle Javadoc.

To make certain whether when hitting exception all the rows are processed
Modify the below code to include a counter i to get processed rows and find actual count of rows
int i=0;
try{
while (rs.next()) {
Interval interval = new Interval(rs.getLong("from_no"), rs.getLong("to_no"));
intervals.put(interval, rs.getString("market_code"));
i=i+1;
}
}
catch (Exception e)
{
Logger.getLogger(getClass().getName()).log(Level.FINE, "the total rows processed"+ i);
Statement stmt = null;
String query = "select count(1) count_rows
from market_codes";
stmt = con.createStatement();
ResultSet rs1 = stmt.executeQuery(query);
rs1.next();
String countRows = rs1.getString("count_rows");
Logger.getLogger(getClass().getName()).log(Level.FINE,"Actual count of rows"+ countRows);
}

It's very strange, but problem has been solved by removing annotation #ConcurrencyManagement(ConcurrencyManagementType.BEAN)
Can anyone explain it?

Related

how do I get spring to recognize the first capital letter using postgresql

I have a question how I can do so that in spring my table is recognized with the first capital letter, is made in postgresql
#Entity
#Table(name="System_user")
public class Dashboard {
#Id
#Column(name = "username")
String username;
get..
set...
}
it generates an error and I change it as shown below
#Table("\"System_user\"")
but he still doesn't recognize me
As we discussed in the comments, the issue was in dialect.
Latest dialect for now - org.hibernate.dialect.PostgreSQL95Dialect
The issue solved this dialect:
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
Answer to your HQL-code:
I would suggest using TypedQuery as it returns not just a list, but list of your object.
Furthermore, u are using the same session to transfer data. This is bad for the program. Always do like Open session - transfer data - close session.
Try this code:
public List<Vw_dh_assay> listAssayReport(double year, String project_id, String hole_id) {
List<Vw_dh_assay> list = new ArrayList<>();
Session session;
try {
session = this.sessionFactory.openSeesion();
TypedQuery<Vw_dh_assay> query = session.createQuery("from Vw_dh_assay where year = :year AND project_id = :project_id AND hole_id = :hole_id", Player.class);
query.setParameter("year", year);
query.setParameter("project_id", project_id);
query.setParameter("hole_id", hole_id);
list = query.getResultList();
System.out.println(list);
session.clear();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
this is my code DAO #Antonio112009
#Override
public List<Vw_dh_assay> listAssayReport(double year, String project_id, String hole_id) {
Session session = this.sessionFactory.getCurrentSession();
String query = ("SELECT DISTINCT year,project_id,hole_id from "
+ "Vw_dh_assay where year = :year AND project_id = :project_id AND hole_id = :hole_id");
List result = session.createQuery(query).setParameter("year", year).setParameter("project_id", project_id)
.setParameter("hole_id", hole_id).list();
System.out.println(result);
return result;
}

connection.prepareStatement("alter session set container=YPDB2").executeUpdate() return 0;

use ojbc7 to connection oracle12c,
execute "alter session set container=ypdb2", it seems not work;
but i use sqlplus to execute, it is work;
here is my code;
OracleDataSource oracleDataSource = new OracleDataSource();
oracleDataSource.setURL("jdbc:oracle:thin:#127.0.0.1:1521/orcl");
Connection connection = oracleDataSource.getConnection("sys as sysdba", "123456");
PreparedStatement preparedStatement = connection.prepareStatement("alter session set container=YPDB2");
log.info("{}",preparedStatement.executeUpdate());
console print 0
it seems to affect the zero row;
Does this mean that the “alter” did not succeed?
it seems a bug of ojbc;
#Test
public void testAlterSession() throws SQLException {
OracleDataSource oracleDataSource = new OracleDataSource();
oracleDataSource.setURL("jdbc:oracle:thin:#127.0.0.1:1521/ypdb9");
Connection sys_as_sysdba_connection = oracleDataSource.getConnection("sys as sysdba", "123456");
int i = sys_as_sysdba_connection.createStatement().executeUpdate("alter session set container=ypdb9");
log.info("i:{}",i);
List<Map<String, Object>> maps = OdbcUtil.resultSetToList(sys_as_sysdba_connection.createStatement().executeQuery("select * from v$pdbs"));
maps.forEach(map->log.info("{}",map));
sys_as_sysdba_connection.createStatement().executeUpdate("alter session set container=cdb$root");
List<Map<String,Object>> maps2 = OdbcUtil.resultSetToList(sys_as_sysdba_connection.createStatement().executeQuery("select * from v$pdbs"));
maps2.forEach(map->log.info("{}",map));
}
In this test, "excuteUpdate(sql)" returns 0,but the "container" does change when I select the pdb again;
i don't know why yet;

Spring Transactions not working - JDBCTemplate is reading uncommitted data

The following Method inserts two records (but doesn't commits them at this point) and it then tries to read one of the uncommitted records from the previous statements. I wrapped the code with Transaction, and set the isolationLevel to "READ_COMMITTED" but this doesn't seems to be working. The read/"SELECT" statement is reading the uncommitted records.
How is this possible? Where am I going wrong? Please see the code below and help me out. I would be really thankful ~
Note :
I am using BoneCP to get the DataSource.
dbConnectionPool.initConnectionPool(dbName) , will fetch a BoneCPDataSource.
#Override public void testDBCalls() {
dBConnectionPool.initConnectionPool("titans");
DataSource dataSource = dBConnectionPool.getDataSource("titans");
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
definition.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
DataSourceTransactionManager txManager = new DataSourceTransactionManager(dataSource); TransactionStatus
transactionStatus = txManager.getTransaction(definition);
try {
try {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = "INSERT INTO groundwater(external_id,source_type) VALUES (12, 13);";
jdbcTemplate.update(sql);
System.out.println("Successfully inserted - 1");
String sql2 = "INSERT INTO groundwater(external_id, source_type,) VALUES(123,45);";
jdbcTemplate.update(sql2);
System.out.println("Successfully inserted - 2");
String sql3 = "select gw_id from groundwater where external_id= 123;";
System.out.println("Result : "+jdbcTemplate.queryForInt(sql3));
txManager.commit(transactionStatus);
System.out.println("Commiting the trasaction...");
} catch (Exception e) {
e.printStackTrace();
txManager.rollback(transactionStatus);
System.out.println("Rolling back the transaction");
}
} finally {
try {
dataSource.getConnection().close();
System.out.println("Closing the connection ...");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
As #M.Denium explained in the comment, I was trying to do everything from a single transaction. Isolation Levels are meant for maintaining consistency across different transactions. I was still learning the concepts, so I took it in a wrong way.

Spring JdbcTemplate and oracle arrayofnumber

I'm using Spring and Oracle database in my solution and i need to execute script
select count(1) from ELEMENTS, table(cast(? as arrayofnumbers)) session_ids
where root_session_id in session_ids.VALUE
but i have a problem with passing input parameter.
i try to pass List or array of BigInteger into
JdbcTemplate.queryForObject("select count(1) from ELEMENTS, table(cast(? as arrayofnumbers)) session_ids
where root_session_id in session_ids.VALUE", Integer.class, INPUT_PARAMS)
but has an Exception:
java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8861)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8338)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9116)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:9093)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:234)
at weblogic.jdbc.wrapper.PreparedStatement.setObject(PreparedStatement.java:357)
Does anyone have the same problem?
EDIT:
Forget to describe arrayofnumber. It's custom type:
TYPE arrayofnumbers as table of number(20)
Found the solution:
final BigInteger[] ids = new BigInteger[]{BigInteger.valueOf(9137797712513092132L)};
int count = jdbc.query("select count(1) from NC_DATAFLOW_ELEMENTS\n" +
" where root_session_id in (select /*+ cardinality(t 10) */ * from table(cast (? as arrayofnumbers)) t)"
, new PreparedStatementSetter() {
public void setValues(PreparedStatement preparedStatement) throws SQLException {
Connection conn = preparedStatement.getConnection();
OracleConnection oraConn = conn.unwrap(OracleConnection.class);
oracle.sql.ARRAY widgets = oraConn.createARRAY("ARRAYOFNUMBERS", ids);
preparedStatement.setArray(1, widgets);
}
}, new ResultSetExtractor<Integer>() {
public Integer extractData(ResultSet resultSet) throws SQLException, DataAccessException {
resultSet.next();
return resultSet.getInt(1);
}
});
out.println(count);
should note that type of array (ARRAYOFNUMBER) should be in upper case

Commit during transaction in #Transactional

Is that possible to perform commit in the method that is marked as Spring's #Transactional?
#PersistenceContext
private EntityManager em;
#Transactional(propagation = Propagation.REQUIRED)
public void saveMembersWithMultipleCommits(List<Member> members)
throws HibernateException
{
Iterator<Member> it = members.iterator();
while (it.hasNext())
{
while (it.hasNext())
{
Member wsBean = it.next();
em.persist(wsBean); // overall commit will be made after method exit
log.info("Webservices record " + wsBean + " saved. " + i++);
}
}
}
I would like to have commit to DB after say each 500 items. Is that possible with aforementioned context?
No, you need to do it programatically using, for instance, the TransactionTemplate API. Read more here.
It would look something like
while (it.hasNext())
{
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
int counter = 0;
while (it.hasNext() && counter++ < 500) {
Member wsBean = it.next();
em.persist(wsBean);
log.info("Webservices record " + wsBean + " saved. " + i++);
}
}
);
}
Your question suggests that you have misplaced your transaction boundary.
You can move the persist call into a private method and make that method transactional instead of the outer one. This method could accept 500 members at a time and then will commit when it exits.
If you are looking forward to committing transactionally inside your other transaction, you might need to use #Transactional (propagation = Propagation.REQUIRES_NEW)
Alternate strategy is you create a method in DAO and mark it #Transactional. This method will do bulk update(for eg 500 nos). So you can have a method with code
#Transactional
public void mybatchUpdateMethod(){
StatelessSession session = this.hibernateTemplate.getSessionFactory()
.openStatelessSession();
Transaction transaction = null;
Long entryCounter = 0L;
PreparedStatement batchUpdate = null;
try {
transaction = session.beginTransaction();
batchUpdate = session.connection().prepareStatement(insertSql);
for (BatchSnapshotEntry entry : entries) {
entry.addEntry(batchUpdate);
batchUpdate.addBatch();
if (++entryCounter == 500) {
// Reached limit for uncommitted entries, so commit
batchUpdate.executeBatch();
}
}
batchUpdate.executeBatch();
batchUpdate.close();
batchUpdate = null;
}
catch (HibernateException ex) {
transaction.rollback();
transaction = null;
}
}
Every time you call this method, it will commit after 500 inserts/updates

Resources