Load Table content from Oracle DB to Spring Bean on server run - java

I have a table in Oracle11 DataBase with two columns (KEY(varchar2),PROPERTY(varchar2)).
By using Spring framework I want to load the whole content (All the rows) from the table to the Spring Bean so that instead of getting value from DataBase all the time I can use the Bean.
I used Bean class "org.apache.commons.configuration.DatabaseConfiguration". It is working fine but this bean class do not have the provision to load the whole table content into it.
PFB, my Spring-config.xml:
<bean name="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="commonsConfigurationFactoryBean"/>
</bean>
<bean name="commonsConfigurationFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfiguration"/>
</bean>
<bean name="databaseConfiguration"
class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
<constructor-arg type="java.lang.String" index="1" value="schema.Table_Name1"/>
<constructor-arg type="java.lang.String" index="2" value="KEY"/>
<constructor-arg type="java.lang.String" index="3" value="PROPERTY"/>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:SYSTEM_NS:PORT:sid"/>
<property name="username" value="xxxx"/>
<property name="password" value="xxxx"/>
</bean>
Java Code:
ApplicationContext classpathCtx = new ClassPathXmlApplicationContext("Spring-config.xml");
DatabaseConfiguration dBConfig = (DatabaseConfiguration)classpathCtx.getBean("databaseConfiguration");
// To display the value in the property column by sending the value of column KEY
System.out.println(dBConfig.getProperty("Value in the KEY column"));
The Above code is working fine. But each time I am sending the key to DatabaseConfiguration it is internally making a DataBase call to get the property which I do not want to happen.
The whole of the above concept is all about trying to store all the data present in .properties to DB and fetching it from the DB to my Java code.

You could create a FactoryBean that creates a properties object by reading all keys from the databaseConfiguration and copying them to the created properties object.
This properties object is then a singleton, and can be used as such in your spring config.
<bean name="properties" class="...ConfigurationPropertiesFactoryBean">
<property name="configuration" ref="databaseConfiguration"/>
</bean>
public class ConfigurationPropertiesFactoryBean implements FactoryBean<Properties>
{
private Properties props = new Properties();
public void setConfiguration(Configuration configuration)
{
props.put ...
}
public Properties getObject()
{
return props;
}
}
Or instead of a DatabaseConfiguration, you could use JdbcTemplate:
<bean name="properties" class="...DataSourcePropertiesFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
public class DataSourcePropertiesFactoryBean implements FactoryBean<Properties>
{
private Properties props = new Properties();
public void setDataSource(DataSource dataSource)
{
props = new JdbcTemplate(dataSource).query("SELECT KEY, PROPERTY FROM ...",
new ResultSetExtractor(){
public void Properties extractData(ResultSet rs)
{
props.put(...);
}
});
}
public Properties getObject()
{
return props;
}
}

Related

Inject BasicDataSource at runtime with spring

I use spring to access to a database :
XML Spring context :
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource">...</bean>
<bean id="jdbcTmp" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds" />
</bean>
<bean id="myDao" class="MyDao">
<property name="jdbcTemplate" ref="jdbcTmp" />
</bean>
Code :
System.out.println("There is : " + new ClassPathXmlApplicationContext("beans.xml").getBean("myDao").countRowsInTheDB() + " rows in this source";
It's simple and it works good. But I want to choose between different databases at runtime according to a variable.
Something like :
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
int rows1 = ctx.getBean("myDao", "dataSource1").countRowsInTheDB();
int rows2 = ctx.getBean("myDao", "dataSource2").countRowsInTheDB();
What is the simpliest way to do that ?
I want to create an XML configuration for each source :
<bean id="myDao1" class="MyDao"><property name="data" ref="jdbcTmpForDataSource1" /></bean>
<bean id="myDao2" class="MyDao"><property name="data" ref="jdbcTmpForDataSource2" /></bean>
And write the code :
int i = getDataSourceIndex();
ctx.getBean("myDao" + i).countRowsInTheDB();
Create a second datasource, jdbc template, dao :
<bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource">... </bean>
<bean id="jdbcTmp2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds2" />
</bean>
<bean id="myDao2" class="MyDao">
<property name="jdbcTemplate" ref="jdbcTmp2" />
Create a bean, that is a list of all datasources
Just autowire it in, spring will inject the list
#Autowired List<DataSource> dataSources;
In your code iterate over the list and do whith the datasourceswhatever you want.

How jdbc connectvity should work in Spring MVC

Below is the way, i am using jdbc connectivity for my spring mvc.
I have some technical doubts, which follows-
1.
As i have invoked datasource object in every bean that requires db connectivity. Is it the right way of doing it?
What if i don't want a particular repository object to be instantiated when the application starts up
(because I'm not sure when user will invoke the object, so why instantiate it at the very beginning)?
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="testConnectionOnCheckout" value="${jdbc.testConnection}" />
</bean>
<bean id="ustestuthenticationRepository"
class="com.test.repository.impl.UstestuthenticationRepositoryImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="someclass"
class="com.test.repository.impl.someclass">
<property name="dataSource" ref="dataSource" />
</bean>
2.
#Qualifier("dbDataSource")
private static DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
and then creating
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
I'm not sure if this is the right way of invoking datasource.If each and every Repository object creates separate jdbctemplate, is it something appropriate?
In every repository class, i am invoking datasource in the folowing way-
Modified Code
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<bean id="someclass" class="com.era.repository.impl.someclass">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
and implementation in someclass is -
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
then only accessing jdbcTemplate variable wherever is required.
Am i doing it correctly now? Please advise.
What you done is not an error. It is possible to work that way.
However.
It means you will simply work with JDBC directly.
It means, you need handle transactions "manually".
It is hard and a lot of code.
You better use spring data and hibernate.
Or spring data and JPA.
Anyway, spring data will help you to manage all resources and will simplify data access for you.
If you already on spring MVC, take also spring data. Why bother?
Official spring data example:
https://spring.io/guides/gs/accessing-data-jpa/

Can't access the database values using JdbcTemplate

I'm trying to insert value into Oracle DB using JdbcTemplate, but its throwing the following exception:
Can't access the database values using JdbcTemplate.
This is how I am trying to insert the values to the DB:
package com.sample.common.Dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class UserDao extends JdbcDaoSupport {
public void insert(){
System.out.println("Tring to insert");
String sql = "INSERT INTO SB_TBL_USER (user_id,user_password,user_name,user_email,user_mobile)"+" "
+"VALUES ('test12', 't1est1', 't2est2', 't7est2','t7estm')";
getJdbcTemplate().update(sql);
}
public static void main(String args[]){
UserDao dao= new UserDao();
dao.insert();
}
}
DataSourceConfiguration.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="sbjdev" />
<property name="password" value="sbjdev" />
</bean>
<bean id="UserDao" class="com.mPowerQuartz.common.Dao.UserDao.java">
<property name="dataSource" ref="dataSource" />
</bean>
This exception is most likely thrown by your own code.
And it's most likely thrown because the dataSource field of the UserDao is null.
The reason for that is that you're not using Spring correctly. Instead of asking Spring to create the UserDao and inject the DataSource in that Spring bean, you're creating the UserDao yourself, using new. So no Spring context is ever used, and Spring doesn't play any role in your code.
Read the Spring documentation to understand how to create a Spring application context and get a bean from it.
I found the answers they are..
1)ApplicationContext and bean is not initialized, which will look like..
ApplicationContext ctx = new ClassPathXmlApplicationContext("userconfig.xml");
UserDao usr = (JobDetailsDao) ctx.getBean("UDao");
2)In configuration xml, Dao and Dao implementation are not mapper. Which looks like.
<bean id="UserDao" class="com.mPowerQuartz.common.DaoImpl.UserDaoImpl">
<property name="jdbcTemplate"> <ref bean = "jdbcTemplate" ></ref>
</property>
</bean>

Mybatis Spring integration

I have a web application (JSF and Managedbeans) using Mybatis without Spring and I want to use Spring in this web application and integrate mybatis with spring.
I have my mybatis-config.xml and the mappers.
I have mappers in xml and interfaces with the same name of the mappers un xml.
Then the classes that implements the interfaces are something like that.
public class LocalidadPersistence implements LocalidadMapper {
#Override
public List<Localidad> getLocalidades() throws SQLException {
List<Localidad> listaLocalidades = null;
SqlSession session = new MyBatisUtil().getSession();
if (session != null) {
try {
listaLocalidades = session.selectList("com.mybatis.mappers.localidad.getLocalidades");
} catch (Exception ex) {
throw new SQLException("Error obteniendo listado Localidades");
} finally {
session.close();
}
} else {
throw new SqlSessionException("Sesion no encontrada");
}
return listaLocalidades;
}}
MyBatisUtil code is this.
public class MyBatisUtil {
private String resource = "com/mybatis/mybatis-config.xml";
private SqlSession session = null;
public SqlSession getSession(){
try{
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
session = sqlMapper.openSession();
}catch (IOException ex){
ex.printStackTrace();
}
return session;
}}
I have been reading something about Mybatis spring integration but I don't understand all very well. I know that my spring xml must be something like that. I have not put the mappersLocation property because I have read that this is not neccesary since i have defined my mappers on mybatis-config.xml.
<context:annotation-config />
<context:component-scan base-package="com" />
<tx:annotation-driven />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/DB" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/com/mybatis/mybatis-config.xml" />
<property name="transactionFactory" ref="springManagedTransactionFactory" />
</bean>
<bean id="springManagedTransactionFactory" class="org.mybatis.spring.transaction.SpringManagedTransactionFactory">
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="registroClimaMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.mybatis.dao.RegistroClimaMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
Also I have no idea about how to use this inside my application after it has been configured with spring. What happen with MyBatisUtil class and the implementation of the interfaces?
When you use mybatis-spring, you will get an implementation of mapper interface automatically from the mybatis. So, you can safely use the interface with #Autowired inside any of your spring beans. That's it. Where there is a spring, there a DI. And yes, with mybatis-spring you don't need MybatisUtil at all as all the task are managed in your spring xml .

Can a bean be a value to another bean in the Spring Framework?

I'm trying to learn spring framework and bean configuration and so far it seems really cool.
I'm about to create a generic class to include all my Mysql functions and it needs to contain the DataSource. My question is: Is it possible to set the datasource already in the bean configuration?
If not then I'll need to set the class as singleton, create an init function and in the init function to do the following:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
DataSource ds = (DataSource) context.getBean("dataSource");
The question is, instead of doing that, can I 'inject' (donno if that's the right term)
it directly in the bean?
this is my bean configuration.
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/foo"/>
<property name="username" value="root"></property>
<property name="password" value="password"></property>
<property name="validationQuery" value="SELECT 1" />
<property name="testOnBorrow" value="true" />
<property name="testWhileIdle" value="true" />
<property name="initialSize" value="5" />
</bean>
<bean id="bar" class="foo.bar">
<property name="dataSource" value="<HERE_SETTING_THE_DATA_SOURCE_ABOVE>" />
</bean>
Is this possible ?
You can reference a bean like your dataSource.
Your class should have a member that can hold the dataSource:
package mypackage;
public class MyBean {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = data.Source;
}
}
Then you can inject the dataSource bean into this bean:
<beans>
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<!-- set properties -->
</bean>
<bean id="myBean" class="mypackage.MyBean">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
That's it.

Categories