Spring repository sends HQL to database server - java

I have a simple spring data repository which extends CrudRepository
Also I configured
<context:component-scan base-package="by.acme.vt.*"/>
and
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="eqDataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- Set JPA properties -->
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="javax.persistence.schema-generation.database.action">none</prop>
</props>
</property>
<!-- Set base package of your entities -->
<property name="packagesToScan">
<array>
<value>by.acme.vt.asdint</value>
<value>by.acme.vt.asd.domain</value>
<value>by.acme.vt.asd.repository</value>
</array>
</property>
</bean>
and
<jpa:repositories base-package="by.acme.vt.*" entity-manager-factory-ref="entityManagerFactory"/>
So
by.acme.vt.asdint
belongs to the project which I am working on but packages
<value>by.acme.vt.asd.domain</value>
<value>by.acme.vt.asd.repository</value>
belongs to the included jar file
If I create the same repo in the project, it works fine but for repositories which were included in jar, even when I run a simple code like
myrepo.findById(id)
It sends a pure HQL to the server, so it does not transform it to SQL at all.
I see response from mssql like.
table MyUser does not exist on server.
But it supposed to use my_user table but not MyUser

Related

Do I need to register all the model class in hibernate config file

Suppose I have number of model classes(Entity class). Do I need to register all the model class in hibernate config file one after another like
...
<mapping class="com.java.ent.Table"/>
...
or any annotation is there which marks as entity? For medium app there would be huge amount of table and its corresponding model entity. how to manage it?
There another way to configure hibernate sessionFactory where you can actually give only packageToScan.
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.connection.useUnicode">true</prop><!-- added -->
<prop key="hibernate.connection.characterEncoding">UTF-8</prop><!-- added -->
<prop key="hibernate.connection.charSet">UTF-8</prop><!-- added -->
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.web.entities</value>
</list>
</property>
</bean>
You can write your own set package in AnnotationConfiguration as described in the dicumentation.
https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/ch01.html
Or
Another option is to write custom AnnotationConfigurationWithWildcard which extends the org.hibernate.cfg.AnnotationConfiguration and inject as spring dependency.
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfigurationWithWildcard"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
You can use which ever suits you better.

configure hibernate to map entities automaticly

I use hibernate ORM in my project.
Now I map entities like this :
<mapping class="entities.User"/>
but I have to do this for each entity I create - is there anything I can put in the hibernate configuration to make it scan itself for annotated entities in certain package?
thank you
You can place all your java entities in a JAR file and then provide the path of the JAR file in hibernate configuration file like this:
<mapping jar="path_to_your_jar_file"/>
Update:
This is helpful only if you have hbm.xml files for mapping instead of having annotations on your classes. These mapping files should be part of the JAR file.
Look at this link for addJar method of Configuration class.
Using spring can help you get the package scanned. See the config below
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan">
<list>
<value>com.tds.hibernate.entities</value>
</list>
</property>
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>

Configuring JPA in Spring application

I am configuring Spring to use JPA by using Hibernate implementation. However I don't understand the process completly. I have gotten it to work by following different blogs etc. I have used EJB 3.1 and there I had a persistence.xml. However in spring I declared a LocalContainer...Bean and provided some properties to it, and I have no persistence.xml. Could someone explain how it works in Spring and what the declared bean is?
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.company.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL82Dialect
</prop>
</props>
</property>
</bean>
There are different flavors of Spring Configuration with JPA, one which requires persistence.xml and other which requires just bean declarations(no persistence.xml).
I am going to take up the Case-2 in your scenario:
The main reasons we want a persistence.xml is because of the following reasons:
Database connectivity details.
Java classes which are treated as Entities or packages in which to scan for Entities.
Other vendor specific settings like hibernate.show_sql or similar stuff.
Now if spring provides a way to mention all this together in bean configurations then there is no need to have the persistence.xml.
In case of your bean definitions, lets break it down.
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.company.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL82Dialect
</prop>
</props>
</property>
</bean>
First property, dataSource already contains the database settings.
Second property, jpaVendorAdapter is a property specific to Spring
Third property, packagesToScan this is a property of Spring to scan for entities, this we either do in persistence.xml by using "class" tags by mentioning each class FQN.
Fourth property, jpaProperties as the name suggests can either be in Spring or in persistence.xml
e.g.
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
Since you have all the configurations already in Spring bean, there's no need to have a persistence.xml
Just to add a FootNote:
Spring 3.1 provides an alternative: LocalContainerEntityManagerFactoryBean that accepts a 'packagesToScan' property, specifying base packages to scan for #Entity classes.
Hope this answer your queries.

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

What is this error about? "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here".
My spring config file looks something like this.
<bean id="jndiDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/devDS</value>
</property>
</bean>
<bean id="stsaDBFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="jndiDataSource" />
<property name="annotatedClasses">
<list>
<value>xx.yy.zz.User</value>
<value>xx.yy.UserResponse</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbmddl.auto">create</prop>
</props>
</property>
</bean>
<!-- ################################### Aspects ################################################## -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="stsaDBFactory" />
</property>
</bean>
All the DAO test passes when i test them outside of the container using junit. When I deploy it in jBoss as a portal app,I get this exception. Also it works fine if i remove the portal specific configuration and make it a simple web app and deploy it on jboss.Any idea?
You have defined a TransactionManager in your spring config but you are trying to execute a hibernate query in a method that is not transactional. Try adding #Transactional to your method or class.
I got around this problem by specifying the current_session_context_class in hibernate config to be "thread", as per the simple configuration shown in the hibernate configuration documentation.
But it recommends that its not safe for production usage.
Trying to add the following in your hibernate config should also help:
<property name="current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>
Check out http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/architecture.html#architecture-current-session for more details.

Spring and hibernate.cfg.xml

How do I get Spring to load Hibernate's properties from hibernate.cfg.xml?
We're using Spring and JPA (with Hibernate as the implementation). Spring's applicationContext.xml specifies the JPA dialect and Hibernate properties:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
</props>
</property>
</bean>
In this configuration, Spring is reading all the Hibernate properties via applicationContext.xml . When I create a hibernate.cfg.xml (located at the root of my classpath, the same level as META-INF), Hibernate doesn't read it at all (it's completely ignored).
What I'm trying to do is configure Hibernate second level cache by inserting the cache properties in hibernate.cfg.xml:
<cache
usage="transactional|read-write|nonstrict-read-write|read-only"
region="RegionName"
include="all|non-lazy"
/>
Try something like this...
<bean
id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>
classpath:location_of_config_file/hibernate.cfg.xml
</value>
</property>
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
The way I've done this before is by instantiating a LocalSessionFactoryBean and setting the configLocation property.

Categories

Resources