Hibernate datasource connection with JNDI - java

I can get connection using JDBC
OracleDataSource ds = (OracleDataSource) Class.forName("oracle.jdbc.pool.OracleConnectionPoolDataSource").newInstance();
//...
Connection connection = ds.getConnection("USER", "PASSWORD");
But I can't do it for Hibernate using hibernate.connection.datasource and jni:
I tried different variants, but it does not work.
String var1 = "oracle.jdbc.pool.OracleConnectionPoolDataSource";
String var2 = "java:/oracle.jdbc.pool.OracleConnectionPoolDataSource";
String var3 = "java:/oracle/jdbc/pool/OracleConnectionPoolDataSource";
String var4 = "java:/OracleConnectionPoolDataSource";
configuration.setProperty("hibernate.connection.datasource",var1);
All variants throw exceptions when it tries to build SessionFactory:
private static SessionFactory createSessionFactory(Configuration configuration) {
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder();
builder.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = builder.build();
return configuration.buildSessionFactory(serviceRegistry);
}
Exceptions like this:
Exception in thread "main" org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [oracle.jdbc.pool.OracleConnectionPoolDataSource]
maven dependecies for it:
<dependency>
<groupId>local.ora9iDriver</groupId>
<artifactId>ora9iDriver</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>C:/Users/micah/.m2/repository/local/ora9iDriver/oraDriver/1.0/ora9i.jar</systemPath>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>9.0.2.0.0</version>
</dependency>

Can you check out the UCP with Hibernate blog and get some pointers?

Related

How to create a table in HBASE using Java API

I want to create a table in HBASE using Java
I found this example to create a table in HBASE
https://www.tutorialspoint.com/es/hbase/hbase_create_table.htm
but these HTableDescriptor and HColumnDescriptor classes appear to me as deprecated and I don't know what alternative I can use so that the deprecated message does not appear
Connection connexion = ConnectionFactory.createConnection(config);
Admin admin = connexion.getAdmin();
////CREATE TABLE
// Instantiating configuration class
//Configuration con = HBaseConfiguration.create();
// Instantiating HbaseAdmin class
//HBaseAdmin admin = new HBaseAdmin(config);
// Instantiating table descriptor class
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("emp"));
// Adding column families to table descriptor
tableDescriptor.addFamily(new HColumnDescriptor("personal"));
tableDescriptor.addFamily(new HColumnDescriptor("professional"));
// Execute the table through admin
admin.createTable(tableDescriptor);
System.out.println(" Table created ");
////////////
How can I create a table in Hbase with the Java api, please help with some code or documentation
I am working with java 1.8.0.112
and the project dependencies are
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase</artifactId>
<version>2.4.1</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
In the more recent versions of the Java API, you can use the class TableDescriptorBuilder and related classes.
Try something like this:
Connection conn; // get the HBase connection as you usually do
Admin admin = conn.getAdmin();
TableDescriptorBuilder tBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf(TABLE_NAME));
ColumnFamilyDescriptor CFD = ColumnFamilyDescriptorBuilder.newBuilder(COL_FAMILY_NAME).build();
TableDescriptor tDesc = tBuilder.setColumnFamily(CFD).build();
admin.createTable(tDesc);
Connection connexion = ConnectionFactory.createConnection(config);
Admin admin = connexion.getAdmin();
byte[] family = Bytes.toBytes("cf");
TableName tname;
tname = TableName.valueOf("MONITOR:ZEMP");
TableDescriptorBuilder tableDescBuilder = TableDescriptorBuilder.newBuilder(tname);
ColumnFamilyDescriptorBuilder columnDescBuilder = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes(ByteBuffer.wrap(family)))
.setCompressionType(Compression.Algorithm.SNAPPY)
.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF);
tableDescBuilder.setColumnFamily(columnDescBuilder.build());
if (!admin.tableExists(tname)) {
TableDescriptor desc = tableDescBuilder.build();
admin.createTable(desc);
System.out.println(" Table created ");
}
else {
System.out.println(" Table already exists ");
}

java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver when using Maven Dependency

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>7.0.47</version>
</dependency>
Above is the maven dependency I'm using.
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:oracle:thin:#//ip:port:ora11g");
p.setDriverClassName("oracle.jdbc.OracleDriver");
p.setUsername("un");
p.setPassword("pw");
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(10);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
p.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);
Connection con = null;
try {
con = datasource.getConnection();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from user");
int cnt = 1;
while (rs.next()) {
System.out.println((cnt++)+". Host:" +rs.getString("Host")+
" User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
}
rs.close();
st.close();
} finally {
if (con!=null) try {con.close();}catch (Exception ignore) {}
}
And above is my database querying test code snippet.
When I'm executing the program I'm getting "java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver" exception.
I searched for the issue and read that I have to "make sure oracle jdbc jar is in the classpath". I'm not sure why do I have to set it manually or is it actually required.
Use below dependency
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
and use below code to connect with your oracle database.
Class.forName("oracle.jdbc.OracleDriver");
String dbURL1 = "jdbc:oracle:thin:{USER}/{PASSWORD}#{URL}:{PORT}:{DBNAME}";
//e.g. String dbURL1 = "jdbc:oracle:thin:tiger/scott#localhost:1521:productDB";
Connection conn1 = DriverManager.getConnection(dbURL1);
if (conn1 != null) {
System.out.println("Connected with connection #1");
}
I resolved the issue by adding the corresponding ojdbc.jar to the project.
It can be resolved by adding the mentioned maven dependency too (mentioned by Joy).
Note that you can download the 19.3 JDBC drivers from central maven

Hibernate 5 Second level Cache is not working , Still fetching from Database

Am planning to implement second level cache with Hibernate 5 .Entity class is annotated with #Cacheable and added strategy as CacheConcurrencyStrategy.READ_WRITE . but its still loooking for data in databse instead of cache .Logs shows 2 SQL queries.
Please see my main method
public static void main(String[] args) {
HolidayDAOImpl holidayImpl = new HolidayDAOImpl();
holidayImpl.setSessionFactory(HibernateUtil.INSTANCE.getSessionFactoryInstance());
holidayImpl.load().forEach(System.out :: println);
System.out.println("Loading second time");
holidayImpl.load().forEach(System.out::println);
}
Please see the HibernateUtil enum
public enum HibernateUtil{
INSTANCE;
public SessionFactory getSessionFactoryInstance(){
Properties properties = new Properties();
properties.setProperty(Environment.URL, "jdbc:mysql://dummy");
properties.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
properties.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver");
properties.setProperty(Environment.USER, "demo");
properties.setProperty(Environment.PASS, "demo");
//second level cache prop
properties.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
properties.setProperty(Environment.USE_QUERY_CACHE, "true");
properties.setProperty(Environment.CACHE_REGION_FACTORY, "org.hibernate.cache.ehcache.EhCacheRegionFactory");
//logging
properties.setProperty("hibernate.show_sql","true");
properties.setProperty("hibernate.format_sql","true");
Configuration cfg = new Configuration();
cfg.setProperties(properties);
cfg.addAnnotatedClass(Holidays.class);
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build();
SessionFactory sessionFactory = cfg.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
}
Please see the DAOImpl class
public List<Holidays> load() {
try (Session session = sessionFactory.openSession()) {
//List<Holidays> result = session.createQuery("from Holidays", Holidays.class).getResultList();
Criteria criteria = session.createCriteria(Holidays.class);
criteria.add(Restrictions.like("holiday_name", "%QA%"));
return criteria.list();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
pom.xml
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.4.1.Final</version>
</dependency>
</dependencies>
While going through some of the stack overflow answers, could understand that in latest version of Hibernate (after version 4), there are some changes in configurations. Not sure i made any mistake in the configurations.
Could anyone please look into it, and figure out why its still looking for database instead of cache?
To use hibernate query cache, you must add setCacheable (true) in each query.
If you add criteria.setCacheable (true); to the DAOImpl class, the second query result comes from the cache.

Spring Data, MySQL, connection dies after 8 hours of inactivity

I am facing an issue where my datasource bean is going down after a period of inactivity. My question is how could I re instantiate the datasource bean that gets hit on application startup.
Here is how we setup the bean on startup.
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
public DataSource dataSource(){
byte[] encryptedFile = fileRetriever.getFile(bucket, key);
String unencryptedJson = fileDecrypter.decryptFile(encryptedFile);
JSONParser parser = new JSONParser();
JSONObject jsonObject = null;
try{
jsonObject = (JSONObject) parser.parse(unencryptedJson);
}catch (Exception ex){
log.error(ex.getMessage());
}
String password = (String)jsonObject.get("password");
DataSource ds = DataSourceBuilder
.create()
.url(url)
.username(userName)
.password(password)
.build();
return ds;
}
This class also has a #Configuration annotation on it.
We have other applications that do not have this issue where the service needs to be bounced after inactivity, but they are also not setting up the data source in this manner and have all the details specified in the application.property file
I have added a custom health check that uses a repository that hits every 30 seconds so that should keep the data source bean alive but incase it does go down I would need a way to recreate it.
Thanks in advance
I assume that boot is configuring the DataSource for you. In this case, and since you are using MySQL, you can add the following to your application.properties up to 1.3
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery=SELECT 1
Might considered a pooled datasource connector. Look at apache dbcb2.
Here is a sample i have that keeps a minimum of 10 idle and increases as needed from the pool.
private static DataSource createDataSource(String url, String userName, String passwrd) throws Exception {
Class.forName(DRIVER).newInstance();
Properties props = new Properties();
props.setProperty("user", userName);
props.setProperty("password", passwrd);
//Create a connection factory that the pool will use to create connections
ConnectionFactory cf = new DriverManagerConnectionFactory(url, props);
//Create the poolable connection factory
PoolableConnectionFactory pcf = new PoolableConnectionFactory(cf, null);
pcf.setValidationQuery("SELECT 1");
pcf.setDefaultAutoCommit(true);
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(10);
poolConfig.setMaxTotal(100);
AbandonedConfig abandonConfig = new AbandonedConfig();
abandonConfig.setRemoveAbandonedTimeout(60);
abandonConfig.setLogAbandoned(false);
abandonConfig.setRemoveAbandonedOnBorrow(true);
abandonConfig.setRemoveAbandonedOnMaintenance(true);
//Create the pool of connections
GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf, poolConfig);
connectionPool.setTestOnBorrow(true);
connectionPool.setTestWhileIdle(true);
connectionPool.setTimeBetweenEvictionRunsMillis(10000);
connectionPool.setMinEvictableIdleTimeMillis(1000);
connectionPool.setAbandonedConfig(abandonConfig);
pcf.setPool(connectionPool);
//Pooling data source itself
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
return dataSource;
}
Maven dependencies for apache dbcb2
<!-- Database connection pools -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>

How to load driver dynamically for Hibernate?

I am loading drivers dynamically for JDBC. It works fine, however this DriverManager becomes useless when I try to open a hibernate session
org.hibernate.service.classloading.spi.ClassLoadingException: Specified JDBC Driver com.mysql.jdbc.Driver could not be loaded
Here is the code
public class TestHibernateSessionFactory {
public void test() throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
URL u = new URL("jar:file:/C:\\Users\\...\\mysql-connector-java-5.1.40-bin.jar!/");
String classname = "com.mysql.jdbc.Driver";
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver)Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new DriverLoader(d));
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306", "admin", "password");
// this is the proof that DriverManager loaded and works fine
System.out.println("CONNECTION OBJECT WORKS FINE: " + con);
// Now I want to try this same technique with hibernate
Session session = null;
Transaction tx = null;
SessionFactory sf = buildSessionFactory("jdbc:mysql://localhost:3306", "admin", "password");
// ERROR Specified JDBC Driver com.mysql.jdbc.Driver could not be loaded WHY ???
session = sf.openSession();
System.out.println(session);
}
private static SessionFactory buildSessionFactory(String myUrl, String myUser, String myPass) {
Configuration configuration = new Configuration();
configuration.configure();
configuration.setProperty("hibernate.connection.url", myUrl);
configuration.setProperty("hibernate.connection.username", myUser);
configuration.setProperty("hibernate.connection.password", myPass);
configuration.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.hbm2ddl.auto", "create-drop");
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
return configuration.buildSessionFactory(serviceRegistry);
}
}
Two questions:
Why doesn't it work with hibernate, but works with jdbc?
How to fix it?
The answer is that the Hibernate will attempt to load the driver from the context (current thread) classloader and it doesn't have the driver. The first part works because you use the classloader that has the driver to create a connection.
The solution could be to use manipulate the context classloader. Just don't forget to clean it up when methods using the loaded driver exit.
The approach to your problem could be something like this:
Idea is to have your own classloader and use that ClassLoader class of yours before initializing your Hibernate SessionFactory
Like this:
Thread.currentThread().setContextClassLoader(myOwnClassLoader);
Though this is not one of the best solutions to address your problem, that is how it is. Though this is an incomplete discussion, it is still useful enough to give you pointers to proceed.
Hope this helps!!!

Categories