I have a very simple test that works with dbcp connection pool and forever hangs with c3p0 (0.9.2).
private String query="select ROWID from SOMETABLE " +
" where rownum <= 100 for update skip locked";
private String deleteQuery = "delete from SOMETABLE where ROWID = ?";
public void retrieve() throws Exception {
while (retrieveChunk() > 0){
//do nothing
}
}
#Transactional
private int retrieveChunk(){
final List<Object[]> delPar = new ArrayList<Object[]>(100);
template.query(query, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
String rowid = rs.getString(1);
delPar.add(new String[]{rowid});
}
});
template.batchUpdate(deleteQuery, delPar);
return delPar.size();
}
Spring context:
<bean id="connPool" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="user" value="**"/>
<property name="password" value="**"/>
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
<property name="jdbcUrl" value="jdbc:oracle:thin:#****"/>
<property name="initialPoolSize" value="0"/>
<property name="maxPoolSize" value="10"/>
<property name="minPoolSize" value="1"/>
<property name="acquireIncrement" value="1"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg>
<ref bean="connPool"/>
</constructor-arg>
</bean>
What is wrong with c3p0 configuration?
Update - log4j output:
12:17:18,449 DEBUG JdbcTemplate:435 - Executing SQL query [select ROWID from SOMETABLE where rownum <= 100 for update skip locked]
12:17:18,465 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,809 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,809 DEBUG JdbcTemplate:881 - Executing SQL batch update [delete from SOMETABLE where ROWID = ?]
12:17:18,824 DEBUG JdbcTemplate:570 - Executing prepared SQL statement [delete from SOMETABLE where ROWID = ?]
12:17:18,824 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,887 DEBUG JdbcUtils:362 - JDBC driver supports batch updates
12:17:18,902 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,902 INFO PlainJdbcTableRetriever:36 - JdbcTemplateRetriever retrieve started
12:17:18,902 DEBUG JdbcTemplate:435 - Executing SQL query [select ROWID from SOMETABLE where rownum <= 100 for update skip locked]
12:17:18,902 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,934 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,934 DEBUG JdbcTemplate:881 - Executing SQL batch update [delete from SOMETABLE where ROWID = ?]
12:17:18,934 DEBUG JdbcTemplate:570 - Executing prepared SQL statement [delete from SOMETABLE where ROWID = ?]
12:17:18,934 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,934 DEBUG JdbcUtils:362 - JDBC driver supports batch updates
12:17:18,934 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,934 DEBUG JdbcTemplate:435 - Executing SQL query [select ROWID from SOMETABLE where rownum <= 100 for update skip locked]
12:17:18,934 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,981 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,981 DEBUG JdbcTemplate:881 - Executing SQL batch update [delete from SOMETABLE where ROWID = ?]
12:17:18,981 DEBUG JdbcTemplate:570 - Executing prepared SQL statement [delete from SOMETABLE where ROWID = ?]
12:17:18,981 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:18,981 DEBUG JdbcUtils:362 - JDBC driver supports batch updates
12:17:18,996 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:18,996 DEBUG JdbcTemplate:435 - Executing SQL query [select ROWID from SOMETABLE where rownum <= 100 for update skip locked]
12:17:18,996 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:19,012 DEBUG DataSourceUtils:327 - Returning JDBC Connection to DataSource
12:17:19,012 DEBUG JdbcTemplate:881 - Executing SQL batch update [delete from SOMETABLE where ROWID = ?]
12:17:19,012 DEBUG JdbcTemplate:570 - Executing prepared SQL statement [delete from SOMETABLE where ROWID = ?]
12:17:19,012 DEBUG DataSourceUtils:110 - Fetching JDBC Connection from DataSource
12:17:19,012 DEBUG JdbcUtils:362 - JDBC driver supports batch updates
Related
I've currently two server who are running a same application, this morning they tried to save at the same time an instance of an object 'Rackstatus'.
The result was :
10:23:37,781 WARN [org.hibernate.util.JDBCExceptionReporter]
(XXXX) SQL Error: 1062, SQLState: 23000
10:23:37,783 ERROR [org.hibernate.util.JDBCExceptionReporter]
(XXXX) Duplicate entry '114464' for key
'PRIMARY' 10:23:37,784 ERROR
[org.hibernate.event.def.AbstractFlushingEventListener]
(XXXX) Could not synchronize database state with
session: org.hibernate.exception.ConstraintViolationException: Could
not execute JDBC batch update
my save code :
public void Save(RackStatus stData) {
Session session = null;
session = super.getSession("BANK");
//Create new instance
Transaction trans = session.beginTransaction();
// execute save
session.save(stData);
// do commit
trans.commit();
}
And finally hibernate definition :
<id name="id" type="int">
<column name="id" />
<generator class="assigned"/>
</id>
Any idea ? Thanks.
I'm trying to configure Hibernate JPA to access database. Without using Hibernate JPA, It accesses to database well, but when using Hibernate JPA it does not.
I'm following this tutorial:
https://www.playframework.com/documentation/2.5.x/JavaJPA
These are my steps:
build.sbt
//Hibernate JPA
libraryDependencies ++= Seq( javaJpa, "org.hibernate" % "hibernate-entitymanager" % "5.1.0.Final" // replace by your jpa implementation )
//JPA
PlayKeys.externalizeResources := false
//Driver for mysql
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.36"
conf/application.conf
db {
# You can declare as many datasources as you want.
# By convention, the default datasource is named `default`
default.driver = "com.mysql.jdbc.Driver"
default.url = "jdbc:mysql://localhost:3306/sakila"
default.username = root
default.password = "root"
default.jndiName=DefaultDS
jpa.default=defaultPersistenceUnit
default.logSql=true
}
conf/META_INF/persistence.xml
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>DefaultDS</non-jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
</properties>
</persistence-unit>
</persistence>
Error messages:
! #70fdppp3i - Internal server error, for (GET) [/count] ->
play.api.Configuration$$anon$1: Configuration error[Cannot connect to database [jpa]]
at play.api.Configuration$.configError(Configuration.scala:154)
at play.api.Configuration.reportError(Configuration.scala:806)
at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:48)
at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:42)
at scala.collection.immutable.List.foreach(List.scala:381)
at play.api.db.DefaultDBApi.connect(DefaultDBApi.scala:42)
at play.api.db.DBApiProvider.get$lzycompute(DBModule.scala:72)
at play.api.db.DBApiProvider.get(DBModule.scala:62)
at play.api.db.DBApiProvider.get(DBModule.scala:58)
at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
Caused by: play.api.Configuration$$anon$1: Configuration error[either dataSource or dataSourceClassName is required]
at play.api.Configuration$.configError(Configuration.scala:154)
at play.api.PlayConfig.reportError(Configuration.scala:996)
at play.api.db.HikariCPConnectionPool.create(HikariCPModule.scala:70)
at play.api.db.PooledDatabase.createDataSource(Databases.scala:199)
at play.api.db.DefaultDatabase.dataSource$lzycompute(Databases.scala:123)
at play.api.db.DefaultDatabase.dataSource(Databases.scala:121)
at play.api.db.DefaultDatabase.getConnection(Databases.scala:142)
at play.api.db.DefaultDatabase.getConnection(Databases.scala:138)
at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:44)
at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:42)
Caused by: java.lang.IllegalArgumentException: either dataSource or dataSourceClassName is required
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:785)
at play.api.db.HikariCPConfig.toHikariConfig(HikariCPModule.scala:141)
at play.api.db.HikariCPConnectionPool$$anonfun$1.apply(HikariCPModule.scala:57)
at play.api.db.HikariCPConnectionPool$$anonfun$1.apply(HikariCPModule.scala:54)
at scala.util.Try$.apply(Try.scala:192)
at play.api.db.HikariCPConnectionPool.create(HikariCPModule.scala:54)
at play.api.db.PooledDatabase.createDataSource(Databases.scala:199)
at play.api.db.DefaultDatabase.dataSource$lzycompute(Databases.scala:123)
at play.api.db.DefaultDatabase.dataSource(Databases.scala:121)
at play.api.db.DefaultDatabase.getConnection(Databases.scala:142)
Error message on screen:
How to solve it?
I'm using Play framework 2.5
I think your jpa.default property is in wrong place. Try like this:
db {
# You can declare as many datasources as you want.
# By convention, the default datasource is named `default`
default.driver = "com.mysql.jdbc.Driver"
default.url = "jdbc:mysql://localhost:3306/sakila"
default.username = root
default.password = "root"
default.jndiName=DefaultDS
default.logSql=true
}
jpa.default=defaultPersistenceUnit
I've seen all sorts of posts on using Spring and MyBatis with transactions, but I'm facing a problem with rollbacks not working with plain old JDBC.
My ( test / throwaway) code is pretty simple : I open a session, insert a rec, throw an error on purpose and rollback the transaction. However, it always commits.
public static void main (String[] args){
//-- omitted for brevity
try {
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sess = sqlSessionFactory.openSession(false);
BillsMapper mapper = sess.getMapper(BillsMapper.class);
BillState billState = new BillState();
billState.setBillId(-1);
billState.setLastName("TESTER");
billState.setFirstName("TESTER");
mapper.insert(billState);
logger.info("Post insert: key = {}", billState.getBillId());
if(1 == 1)
throw new RuntimeException("Error Thrown on purpose...testing rollback ");
sess.commit();
}catch(Exception e){
logger.error("Error: {}", e);
sess.rollback();
}finally{
sess.close();
logger.info("Finito!");
}
}
The logs show:
DEBUG | (BaseJdbcLogger.java:145) - ==> Preparing: insert into bills (users_userId, refId, firstName, ...
DEBUG | (BaseJdbcLogger.java:145) - ==> Parameters: 67(Integer), 67-120530180328(String), TESTER(String), ...
DEBUG | (BaseJdbcLogger.java:145) - <== Updates: 1
INFO | (TestAction.java:50) - Post insert: key = 2478
ERROR | (TestAction.java:56) - Error: {} java.lang.RuntimeException: Error Thrown on purpose...testing rollback at com.s2stest.TestAction.main(TestAction.java:53)
DEBUG | (JdbcTransaction.java:79) - Rolling back JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (JdbcTransaction.java:122) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (JdbcTransaction.java:90) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection#371e88fb]
DEBUG | (PooledDataSource.java:344) - Returned connection 924748027 to pool.
Note the resetting of autocommit before closing the connection.... Would resetting autcommit before closing the SqlSession cause my rolled-back transaction to be committed? If so, is this a bug? Has anyone gotten JDBC working with transactions? I need it for testing, and I'd value some help. Right now, no transactions can be rolled back.
I've looked at the MyBatis source, and it indeed calls resetAutocommit before closing the connection. I'm using MySQL 5.6 and mysql-connector-java-5.1.36.jar for the driver if someone has a workaround that they've found.
--- UPDATE ---
mybatis-config.xml is as follows:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="SLF4J" />
</settings>
<typeAliases>
<package name="com.ship2storage.domain" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mytestDb?zeroDateTimeBehavior=convertToNull" />
<property name="username" value="--shhh!!--" />
<property name="password" value="--shhh!!--" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/ship2storage/db/maps/BillsMapper.xml" />
</mappers>
</configuration>
OK, I've found the answer by digging deeper into my setup. It seems that the MySQL storage engine I installed for my test DB is ISAM. ISAM does not support transactions. I switched to InnoDB using the following SQL tidbit, and transactions now work with JDBC:
ALTER TABLE bills ENGINE=InnoDB;
I haven't tried this, but it looks like you can also do this temporarily too:
SET default_storage_engine=InnoDB;
Hopefully this will help someone. The code/config posted above works.
My code is below. Possibly I am using it many times in similar manner, i.e in simple words, I am managing the session and transaction this way:
List<Login> users= null;
try{
session=HibernateUtil.getSessionFactory().getCurrentSession();
tx=session.beginTransaction();
users=session.createQuery("from Login").list();
tx.commit();
}catch(Exception e){System.out.println("commit exception:"+e);
try {tx.rollback();} catch (Exception ex) {System.out.println("rollback exception:"+ex);}
}finally{if(session!=null && session.isOpen()){session.close();}}
return users;
Now, when I first run the database service(using MySQL) and check from command prompt using this query ...
show status like 'Conn%';
... the result is:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Connections | 2 |
+---------------+-------+
When I start my application and use it. After opening few pages and querying the same thing. I am getting the connections as 6, I have even seen above 20.
Now I would like to know that hibernate is closing the connections or not?
I am handling all the transactions that way, I cross checked and dint see any code block without closing the session.
Hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/shareapp
</property>
<property name="connection.username">pluto</property>
<property name="connection.password">admin</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
</session-factory>
hibernateutil class
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass(Login.class);
config.addAnnotatedClass(FilesInfo.class);
config.addAnnotatedClass(FilesShare.class);
config.configure("hibernate.cfg.xml");
// new SchemaExport(config).create(true,true);
sessionFactory = config.buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Thanks!
The "Connections" status variable just refers to the
The number of connection attempts (successful or not) to the MySQL server,
and not the number of active connections.
Here is the link: http://dev.mysql.com/doc/refman/5.1/en/server-status-variables.html#statvar_Connections
To get the number of open connections, check the 'Threads_connected' variable, documented at
http://dev.mysql.com/doc/refman/5.1/en/server-status-variables.html#statvar_Threads_connected
as our connection is very unstable we have decided to switch to our local read-only database if a query times out.
But here is my problem: I do not get an exception when javax.persistence tries to query:
// Attribute
EntityManagerFactory entityManagerFactory;
EntityManager manager;
entityManagerFactory = Persistence
.createEntityManagerFactory("org.hibernate.tutorial.jpa");
manager = entityManagerFactory.createEntityManager();
try {
Query query = manager.createQuery(String.format(
"SELECT u FROM User u WHERE u.id = '%s'", 116));
User user = (User) query.getSingleResult();
manager.refresh(user);
System.out.println(user.getUsername());
} catch (org.hibernate.QueryTimeoutException ex) {
throw new QueryTimeoutException("timeout");
}
}
This is just a test to demonstrate my problem.
What am I missing?
Mysql: mysql-connector-java-5.1.16-bin.jar
JPA: javax.persistence_2.0.3.v201010191057.jar
Hibernate:
115 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.2.0.Final
124 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.6.7.Final
126 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found
129 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist
132 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling
208 [main] INFO org.hibernate.ejb.Version - Hibernate EntityManager 3.6.7.Final
persistence.xml:
<properties>
<property name="hibernate.hbm2ddl.auto" value="valide"/>
<property name="hibernate.connection.url" value="jdbc:mysql:///database?zeroDateTimeBehavior=convertToNull"/>
<property name="hibernate.connection.username" value="user"/>
<property name="hibernate.connection.password" value="pass"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.query.timeout" value="1"/>
<property name="dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
Thank you
Tobias
Solution:
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://server/database", "user", "pass");
Every time I want to start a query I test if the Connection is alive:
if (connection.isValid(1)) {
return true;
} else {
throw new NoConnectionException();
You may not be seeing a timeout because some DBs don't support that feature.
"javax.persistence.query.timeout query timeout in milliseconds
(Integer or String), this is a hint used by Hibernate but requires
support by your underlying database."
See http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html for more details.
I'd be inclined to switch to the read only all the time if you can't guarantee a reliable connection.