I'm using latest springframework disto v4.2.5.RELEASE and Hibernate v5.0.7.Final when spring loads EntityManagerFactory i'm getting the below exception
Caused by: org.hibernate.HibernateException: Not all named super-types (extends) were found : [com.sample.model.Sample]
at org.hibernate.boot.model.source.internal.hbm.EntityHierarchyBuilder.buildHierarchies(EntityHierarchyBuilder.java:76)
at org.hibernate.boot.model.source.internal.hbm.HbmMetadataSourceProcessorImpl.<init>(HbmMetadataSourceProcessorImpl.java:66)
at org.hibernate.boot.model.source.internal.hbm.HbmMetadataSourceProcessorImpl.<init>(HbmMetadataSourceProcessorImpl.java:40)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.<init>(MetadataBuildingProcess.java:142)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:141)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:319)
The same code was working with v4.2.5.RELEASE and Hibernate v.4.3.10.
I know Hibernate changed core metadata building in v5.x, is there anything needs to be specified in spring config of JPA/EntityManagerFactory/Hibernate Properties to make it work with Hibernate 5.x?
#Entity
#Table(name = "tbl_sample")
public class Sample extends Auditable {
private Long id;
#ManyToOne
#JoinColumn(name = "relationA", nullable = true)
private RelationA relationA;
... etc
}
#MappedSuperClass
public abstract class Auditable extends Persistable {
//audit props
}
#MappedSuperClass
public abstract class Persistable {
//common props
}
I could able to narrow down the issue after enabling trace log, there was one more class which is extending Sample Class and its mapped using hbm.xml like below
<hibernate-mapping package="com.sample.model">
<joined-subclass name="BloodSample" table="tbl_blood_sample"
extends="com.sample.model.Sample">
<key column="ID" />
<property name="sampleNo" column="sampleNo"/>
etc....
</joined-subclass>
The moment i removed this relation hbm it started working... Still wondering why its happening now which was not in older version of hibernate.
So i guess this issue is nothing to do with spring but something related hibernate. Any insight ?
I have a similar your issue.
You try to class tag instead joined-subclass tag in hbm.xml file
Related
I am using JPA annotations to map entities in my model. However, I found Hibernate Criteria is easy to use and contains less codes to write, so is there some way to use Criteria without mapping with hibernate xml ways? I tried this in my DAO implementation class:
private SessionFactory sFactory; // of type org.hibernate.SessionFactory
....
Session session = sFactory.getCurrentSession();
Criteria criteria = session.createCriteria(BTerminal.class);
But, without hibernate.cfg.xml it's giving nullpointerexception. Of course because it is not injected. But to fill this cfg.xml I have to add mapping xml files, which is not the way I like. So, can I use JPA mapping while using Hibernate Criteria?
I am not using Spring. Still doubt which is easier: write 10+ mapping xmls with all atributes, or to learn more about Spring DaoSupport, or any other ways.
Thanks in advance.
Yes, it will work. You can have JPA annotated entities, while you use Hibernate Criteria to query your entities, instead of JPA Criteria.
I have actually have tested it.
My entity class looks like this:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class TestEntity {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Version
private Long version;
...
}
Then, I have Hibernate config file: hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="hbm2ddl.auto">create</property>
<property name="show_sql">true</property>
<mapping class="com.test.model.TestEntity" />
</session-factory>
</hibernate-configuration>
Notice, that I still have to list down the entity classes, but I'm not using Hibernate mapping files (hbm.xml). I don't think that Hibernate has support for auto-detection of entity classes, like JPA does (so you still have to list them down even if they are annotated).
Then I have this code as a test, persist entity then retrieve using Hibernate Criteria:
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
TestEntity testEntity = new TestEntity();
testEntity.setName("test");
session.save(testEntity);
List<TestEntity> tests = (List<TestEntity>) session.createCriteria(TestEntity.class).list();
for (TestEntity test : tests) {
System.out.println(test.getName());
}
session.getTransaction().commit();
I have the ff. output in my console:
Hibernate: insert into TestEntity (name, version) values (?, ?)
Hibernate: select this_.id as id1_0_0_, this_.name as name2_0_0_, this_.version as version3_0_0_ from TestEntity this_
test
I've been banging my head on the wall for the past couple of days trying to get this to work but I've not been able to.
I wrote a JPA EntityManagerProvider recently using EJB:
EntityManagerProviderBean.java
#Stateless
public class EntityManagerProviderBean {
#PersistenceContext(unitName="PU1")
private EntityManager entityManager1;
#PersistenceContext(unitName="PU2")
private EntityManager entityManager2;
public EntityManager getEntityManager() {
return (...) ? entityManager1: entityManager2;
}
}
And then of course I can inject the EJB wherever needed like this:
UserFacade.java
#Stateless
public class UserFacade {
#EJB
private EntityManagerProviderBean emProvider;
private EntityManager em = emProvider.getEntityManager();
...
}
Now I'm trying to do something similar using Spring, using annotations, and without doing anything in XML. I can't seem to figure out a way to inject the EntityManager. Anything that I do leads to a NullPointerException. For example, I tried to inject the EntityManager manually without relying on my EntityManagerProviderBean, like this:
UserFacadeSpring.java
public class UserFacadeSpring {
#PersistenceContext(unitName="PU1")
private EntityManager em;
...
}
But this gives me a NullPointerException. So the EntityManager is not being injected at all and I'm not sure what's wrong.
So two questions basically:
How can I inject the EntityManager using Spring?
How can I use my existing EntityManagerProviderBean EJB in Spring? What modifications do I need to make?
Any help in this matter will be greatly appreciated. As you can tell I'm a complete noob to Spring. I tried to read the guide but everything's flying over my head at the moment. I actually did try to do something half-baked but it didn't work either (I either get NullPointerException or BeanNotFoundException, I must have used every combination of #Component, #Bean, #Autowired annotations I think!):
EntityManagerProviderSpring.java
#Component
public class EntityManagerProviderSpring {
#PersistenceContext(unitName="PU1")
private EntityManager entityManager1;
#PersistenceContext(unitName="PU2")
private EntityManager entityManager2;
#Bean
public EntityManager getEntityManager() {
return (...) ? entityManager1: entityManager2;
}
}
Main.java
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(EntityManagerProviderSpring.class);
EntityManagerProviderSpring emProvider = context.getBean(EntityManagerProviderSpring.class);
EntityManager em = emProvider.getEntityManager();
...
}
Thanks!
EDIT: I'm using Hibernate with JPA and the following is my persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="PU1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>...</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/db1?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="pu1_username"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="pu1_pwd"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
</properties>
</persistence-unit>
<persistence-unit name="PU2" transaction-type="RESOURCE_LOCAL">
...
</persistence-unit>
</persistence>
To have the exact same functionality on dependency injection level, it is impossible to map stateless ejb bean to a spring bean.
EJB #Singleton -> Spring #Component (or #Service or #Controller or #Repository)
EJB #Stateful -> Spring #Component#Scope("prototype") (or #Service#Scope("prototype") or #Controller#Scope("prototype") or #Repository#Scope("prototype"))
EJB #Stateless -> DOES NOT EXIST IN SPRING.
Stateless beans are very handy for this multiple persistence contexts... However, since Spring doesn't offer stateless bean. You have to use custom Spring setup to apply multiple persistence context. It won't work with only persistence.xml like EJB, unfortunately :(.
So to answer your questions:
Read Spring doc... Plenty of examples everywhere. Shortly, In Spring 4 Java Config you can use #EnableTransactionManagement, a transaction manager and an entity manager factory per persistence context.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/ejb.html. This is how you do it. Not a nice way since using jndi, but it is a solution...
I have a singleton service class like the below.
#Service
public class SingletonClass{
#Autowired
private ContextProvider provider;
public Context run(){
context = provider.createContext();
updateContext(context)
}
ContextProvider class:
public abstract class ContextProvider implements MyInterface{
public abstract Context createContext();
}
configuration:
<bean name="provider"
class="xyz.s.s.ContextProvider" >
<lookup-method name="createContext"
bean="someBean" />
</bean>
<bean id="somebean" class="com.x.y.someclass" />
<bean id="singletonService" class="com.x.y.SingletonClass" />
When i try to run the above using Junit ->instead of creating the lookup bean on demand, I am getting the below error
org.springframework.beans.factory.BeanCreationException:
aused by: java.lang.AbstractMethodError
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1585)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
It seems, the lookup method injection is not working in my case
I found the issue and fixed it.
I was having the abstract class implemented an interface. So at run time,
CGLIB unable to create a proxy class since there are unimplemented methods.
Compiler also did not complain, because this is abstract class and it did not expect us to add all implementations of the interface.
I removed the 'implements ' and it just works fine.
So the contextprovider will become,
public abstract class ContextProvider {
public abstract Context createContext();
}
Posting this message, since people might face same situation.
I was following a simple tutorial to test the behavior of spring data rest, with annotating a repository with #RestResource annotation.
I have very simple scenario:
Jpa User Entity and UserRepository annotated with #RestResource
#RestResource(path="users", rel="users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
List<User> findUserByUserName(#Param("userName")String userName);
}
I use annotation config initialization and I try to register RepositoryRestMvcConfiguration, so the UserRepository can be registered.
But my application is not starting and I have the following exception
INFO Registering annotated classes: [class org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration,class com.ncau.WebMvcConfiguration]
ERROR Context initialization failed
java.lang.ClassCastException: [Lorg.springframework.hateoas.config.EnableHypermediaSupport$HypermediaType; cannot be cast to org.springframework.hateoas.config.EnableHypermediaSupport$HypermediaType
at org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar.registerBeanDefinitions(HypermediaSupportBeanDefinitionRegistrar.java:90) ~[spring-hateoas-0.8.0.RELEASE.jar:na]
I use
spring-hateoas: 0.8.0.RELEASE
spring-data-rest-webmv: 2.0.0.RC1
spring-framework: 4.0.0.RELEASE
spring-data-jpa:1.4.3
For SDR 2.0.0.RC1, use
spring-hateoas 0.9.0.RELEASE
spring-data-jpa 1.5.0.RC1
SDR will export all repositories by default, you don't need to annotate them.
I'm trying to inject spring bean into JSF bean, I'm using Spring 3.1 and JSF 2 (Mojarra 2.1.7)
Without a lot of talking my configuration and code and exception listed in the following:
StudentService.java:
#Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
public class StudentsService extends AbstractMaqraaService {
#Override
public Set<Class<?>> getTypes() {
// TODO Auto-generated method stub
return null;
}
public Student registerStudent(Student student) {
return this.store(student);
}
}
StudentRegistrationMBean.java:
#ManagedBean(name="studentRegistrationMBean")
#SessionScoped
public class StudentRegistrationMBean extends AbstractMBean {
private Student student;
#ManagedProperty (value="#{studentsService}")
private StudentsService studentsService;
public StudentRegistrationMBean() {
this.student = new Student();
}
/*Setters and getters omitted here only*/
public String register() {
studentsService.registerStudent(student);
return "manageStudents";
}
}
Spring bean in module context xml file:
<bean id="abstractMaqraaService" class="org.tts.maqraa.service.AbstractMaqraaService" abstract="true"/>
<bean id="studentsService" class="org.tts.maqraa.service.StudentsService" lazy-init="default" parent="abstractMaqraaService"/>
faces-config.xml:
...
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
...
Eception:
TRACE [http-bio-8080-exec-3] (SpringBeanELResolver.java:53) - Successfully resolved variable 'studentsService' in Spring BeanFactory
DEBUG [http-bio-8080-exec-3] (AbstractBeanFactory.java:245) - Returning cached instance of singleton bean 'studentsService'
نوار 13, 2012 11:10:45 ص com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/teacher/registerNewStudent.xhtml]
com.sun.faces.mgbean.ManagedBeanCreationException: Unable to set property studentsService for managed bean studentRegistrationMBean
at com.sun.faces.mgbean.ManagedBeanBuilder$BakedBeanProperty.set(ManagedBeanBuilder.java:615)
at com.sun.faces.mgbean.ManagedBeanBuilder.buildBean(ManagedBeanBuilder.java:133)
...
at java.lang.Thread.run(Unknown Source)
Caused by: javax.el.ELException: Cannot convert org.tts.maqraa.service.StudentsService#8f65bc0 of type class $Proxy10 to class org.tts.maqraa.service.StudentsService
at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:420)
at org.apache.el.ExpressionFactoryImpl.coerceToType(ExpressionFactoryImpl.java:47)
at com.sun.faces.el.ELUtils.coerce(ELUtils.java:536)
at com.sun.faces.mgbean.BeanBuilder$Expression.evaluate(BeanBuilder.java:592)
at com.sun.faces.mgbean.ManagedBeanBuilder$BakedBeanProperty.set(ManagedBeanBuilder.java:606)
... 47 more
ERROR [http-bio-8080-exec-3] (MaqraaExceptionHandler.java:83) - Exception
javax.el.ELException: Cannot convert org.tts.maqraa.service.StudentsService#8f65bc0 of type class $Proxy10 to class org.tts.maqraa.service.StudentsService
at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:420)
...
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I made a lot of search in Google and found a lot of questions here had issues like mine but nothing helped me, I hope I'll find my solution for my special case !!
use <aop:aspectj-autoproxy proxy-target-class="true"/> to enforce use of JDK proxy rather than CGLIB
if you inject your Spring service like this don't forget to create the setter for your Service:
#ManagedProperty (value="#{studentsService}")
private StudentsService studentsService;
public void setStudentsService (StudentsService studentsService)
{
this.studentsService = studentsService;
}
With the #Autowired annotation there was no need to do this.
Take a look at this answer It's about not using an interface for using your proxy.