I want to insert some data in a table of database after the SessionFactory of spring hibernate has been created.
I have a CUSTOMER table and I want to insert a particular Customer into this table if the Customer doesn't exist.
This is the configuration of SessionFactory:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="packagesToScan" value="com.edfx.adb.persist.entity" />
<property name="entityInterceptor" ref="entityInterceptor" />
</bean>
I know that there is an option hibernate.hbm2ddl.import_files from which we can mention a sql file and the query will be executed at the time of SessionFactory initialization. But I don't want to follow this way.
Also I have found that we can use ServletContextListener for this kind of purpose, but I am not sure this is a good way to achieve what I want. Because what I understand is the listener will be initialized after deployment of war file, when the first user hit the application. So if I have a Scheduler which operates of the Customer and if the Scheduler get executed before any user hit the app, then the Scheduler wouldn't find that need-to-be-insert data.
Any pointer would be very helpful to me.
You can extend org.springframework.orm.hibernate4.LocalSessionFactoryBean and override buildSessionFactory() method to according to your requirement.
Related
I have the following Spring/Hibernate configs:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="jndiDataSource" />
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
I am extensively using spring transaction annotations to control transaction propagation methods throughout my code base. It is all working great.
I have a need to perform an update that will affect many rows at once and I want to blend it in with the rest of my transaction logic. The last thing I want to do is to bull in a china shop and load all objects into memory and loop through them changing them one at a time.
I am trying something like:
#Autowired
private SessionFactory sessionFactory;
...
String hql = "UPDATE TABLE_NAME SET COLUMN_LIST WHERE ID IN :list";
// I see the transaction and get an error when I try to start a new one.
Transaction trans = sessionFactory.getCurrentSession().getTransaction();
Query query = sessionFactory.getCurrentSession().createSQLQuery(hql);
query.setParameterList("list", listOfIds);
success = (query.executeUpdate() == listOfIds.size());
I have tried dropping this into a method with its own transaction instructions, but am not seeing any evidence that it is being executed (other than a lack of errors).
What is the recommended way to include custom Hibernate SQL into Spring managed transactions?
Thanks a lot.
I'm using Spring 3 and hibernate 4.
Here is my root-context.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/musicstore"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="sessionFactory" name="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="packagesToScan" value="domain" /><!--
entity -->
</bean>
And I've got this :
WARN : org.hibernate.engine.jdbc.internal.JdbcServicesImpl - HHH000342: Could not obtain connection to query metadata : Unknown database 'musicstore'
When I deploy my project in tomcat, I want hibernate will create the schema if it's not exist. I have tried hibernate.hbm2ddl.auto= create but it's not working
Are there any ways to do create the schema automatically at run time ? Any suggestions would be helpful :D
Thanks in advance.
I don't know how to solve your problem in a hibernate specific way, but a cool thing about MySQL is that you can (at the very least under certain conditions) specify for the Database itself to be created if it doesn't already exist via the connection string by appending "?createDatabaseIfNotExist=true" to the end.
So, by changing your Spring config to the following you should get the results you need.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/musicstore?createDatabaseIfNotExist=true"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="sessionFactory" name="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="packagesToScan" value="domain" /><!--
entity -->
</bean>
It's worth noting that I don't know anything more about this than that it works, so it may very well have limitations of which I am unaware.
Hibernate requires the database to exist: it cannot help you create the database. If you need to create the database the you will need to implement another solution that executes before Hibernate is initialized.
As you are using Spring the following may be useful for executing the initial 'CREATE DATABASE X' statement.
http://docs.spring.io/spring-framework/docs/3.0.0.RC3/reference/html/ch12s09.html
You obviously need to ensure the initailization executes before the sessionFactory bean is initialized.
You would also likely define 2 datasources, one configured as outlined at the link provided by mretierer (Create MySQL database from Java) i.e. with no database defined and which is used by the Spring db initializer bean and one for use by Hibernate which references the database created during initialization.
No idea if any of this will work but looks feasible...
First the answer to your question: The property you already supplied should do what you were asking for.
<prop key="hibernate.hbm2ddl.auto">update</prop>
The exception your are getting refers to a different problem. Hibernate can't connect to the database you specified.
Pls check your connection string
<property name="url" value="jdbc:mysql://localhost:3306/musicstore"></property>
I am new to Hibernate and am having some issue with its configuration. I am trying to setup a read-only connection to a preexisting Oracle database. I do not want Hibernate to execute any DML/DDL and alter the database schema, yet every time I try deploying my project, this is the message I see:
INFO: updating schema
SEVERE: Unsuccessful: create table WILLOEM.SAMPLE_INFO (SAMPLE_ID varchar2(255) not null, CELL_LINE varchar2(255), STUDY_ID varchar2(255), primary key (SAMPLE_ID))
SEVERE: ORA-00955: name is already used by an existing object
No damage is being done here, since the table creation failed, but I don't want to create a situation where data can be lost. How can I configure Hibernate to act in a read-only manner? Can I prevent statement execution completely, without adding a new Oracle user that lacks the privileges?
Here is my current Hibernate configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>oracle.jdbc.OracleDriver</value></property>
<property name="url"><value>jdbc:oracle:thin:#source.db.somewhere.com:1524:WILLOEM</value></property>
<property name="username"><value>username</value></property>
<property name="password"><value>password</value></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="packagesToScan" value="com.willoem.project.hibernate" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
you could change
<prop key="hibernate.hbm2ddl.auto">update</prop>
to
<prop key="hibernate.hbm2ddl.auto">validate</prop>
this validates the schema, but it will not make any no changes to it.
I'm having a weird problem using Spring and Hibernate. I started using Hibernate using this in hibernate.cfg.xml:
<property name="hbm2ddl.auto">create</property>
It worked fine, and Hibernate successfully created the tables needed in the database.
Now I'm using Spring and my bean used for hibernate in applicationContext.xml looks like this:
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="mappingResources">
<list>
<value>domain/Entity.hbm.xml</value>
<value>domain/Service.hbm.xml</value>
<value>domain/User.hbm.xml</value>
<value>domain/Arcos.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2dll.auto">create</prop>
</props>
</property>
</bean>
I had to drop the tables created by Hibernate at some point but Spring doesn't create them. I tried with create-drop instead of create (just in case someone asks). My DB Schema changed since I used Hibernate and I'm using a lot of getBeans("..."); in my code so it kind of bother me to reuse my Hibernate-only version just to create the tables. I also could create the table by hand, but what would be the point of using these frameworks?
I'm sure I'm doing something wrong somewhere, but I cannot find it. The console prompt an error saying there is no table named "the name of the table", so it connects to the DB successfully.
Thanks for your time :)
hibernate.hbm2dll.auto --> hibernate.hbm2ddl.auto
DLL = Dynamic Link Library
DDL = Data Definition Language
There's a typo in your code
<prop key="hibernate.hbm2ddl.auto">create</prop>
in the solution
In my spring dao configuration xml I currently have to manually list out the domain classes names. Is there any way to automate this to eliminate the need to manually list out a domain class whenever a new one is created?
To give a better idea of what I want to do this, using something similar to component-scan or such
Current code
<bean id="daoSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="applicationDataSource" />
<property name="annotatedClasses">
<list>
<value>com.greenwhich.application.domain.Driver</value>
<value>com.greenwhich.application.domain.DriverRealTimeCurrentLocation</value>
<value>com.greenwhich.application.domain.Journey</value>
<value>com.greenwhich.application.domain.Customer</value>
<value>com.greenwhich.application.domain.SystemConstants</value>
<value>com.greenwhich.application.domain.DriverRequest</value>
<value>com.greenwhich.application.domain.Account</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
All I require that the values under the "annotatedClasses" property is automatically detected
Is there any way to implement this? So far I have tried inserting a component-scan inside of the "annotatedClasses" property searching for the "Entity" annotation which did not work
Any help is greatly appreciated
You should be able to replace the annotatedClasses property with:
<property name="packagesToScan" value="com.greenwhich.application.domain" />
as part of your session factory configuration.