I'm kinda new with the Spring's transaction management. I think I'm missing some configuration but I can't deal with it.
The error is that I'm getting failed to lazily initialize a collection of role exception.
I'm using Spring Data for my DAO. Also, I know about setting the fetchType to Eager but this is what I'm trying to avoid.
DAO:
public interface CourseDao extends CrudRepository<CourseEntity, Long> {
CourseEntity findByName(String name);
}
Service:
#Service
public class CourseMaterialSearchService {
private final CourseDao courseDao;
private final CourseMaterialEntityTransformer courseMaterialEntityTransformer;
#Autowired
public CourseMaterialSearchService(CourseDao courseDao, CourseMaterialEntityTransformer courseMaterialEntityTransformer) {
super();
this.courseDao = courseDao;
this.courseMaterialEntityTransformer = courseMaterialEntityTransformer;
}
#Transactional
public List<CourseMaterial> findMaterialsFor(final Long courseId) {
final CourseEntity entity = courseDao.findOne(courseId);
final List<CourseMaterialEntity> materials = entity.getCourseMaterialEntityList();
return courseMaterialEntityTransformer.transformEntities(materials);
}
}
And my application-context.xml is (of course this is just the relevant part):
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="example" />
<property name="dataSource" ref="exampleDataSource" />
<property name="packagesToScan" value="com.example.example.**.repository" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
When I call the findMaterialsFor method in CourseMaterialSearchService, the exception occurs. How should I solve this?
Any suggestions will be appreciated.
Thank you guys.
Stacktrace:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.example.course.repository.domain.CourseEntity.courseMaterialEntityList, could not initialize proxy - no Session
org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
com.example.example.course.service.transform.CourseMaterialEntityTransformer.transformEntities(CourseMaterialEntityTransformer.java:15)
com.example.example.course.service.CourseMaterialSearchService.findMaterialsFor(CourseMaterialSearchService.java:29)
CourseMaterialEntityTransformer:
public class CourseMaterialEntityTransformer {
public List<CourseMaterial> transformEntities(final Iterable<CourseMaterialEntity> entities) {
final List<CourseMaterial> result = new ArrayList<>();
for (final CourseMaterialEntity entity : entities) {
result.add(transformEntity(entity));
}
return result;
}
public CourseMaterial transformEntity(final CourseMaterialEntity entity) {
final CourseMaterial result = new CourseMaterial();
result.setId(entity.getId());
result.setName(entity.getName());
result.setCourseName(entity.getCourseEntity().getName());
result.setCurrentFileName(entity.getCurrentFileName());
result.setOriginalFileName(entity.getOriginalFileName());
result.setCategory(entity.getMaterialCategoryEntity().getName());
result.setUploader(entity.getUserEntity().getName());
return result;
}
}
com.example.example.course.service.transform.CourseMaterialEntityTransformer.transformEntities(CourseMaterialEntityTransformer.java:15):
for (final CourseMaterialEntity entity : entities) {
CourseEntity:
#Entity(name = "courses")
public class CourseEntity {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "courseEntity")
private List<CourseMaterialEntity> courseMaterialEntityList;
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public List<CourseMaterialEntity> getCourseMaterialEntityList() {
return courseMaterialEntityList;
}
public void setCourseMaterialEntityList(final List<CourseMaterialEntity> courseMaterialEntityList) {
this.courseMaterialEntityList = courseMaterialEntityList;
}
}
Spring applies transactions using AOP. AOP on beans is only applied to beans in the same application context.
You have a <tx:annotation-driven /> in your application-context.xml, which is loaded by the ContextLoaderListener. This file contains a <context:component-scan /> which detects the #Service.
However if you also have the same <context:component-scan /> in the file loaded by the DispatcherServlet, or at least if the same #Service is detected it results in another instance of this service which will not have AOP applied.
As a general rule-of-thumb you want to load everything BUT #Controllers in your ContextLoaderListener and only web related things (view resolvers, #Controllers) in your DispatcherServlet.
See context depended scan-component filter.
You are trying to access a lazy-loaded attribute outside of a transaction. The object then has no connection with the EntityManager (database), since it's outside of a transaction, and thus cannot go fetch the lazy-loaded attribute.
By default Collections are lazy-loaded . You can replace below your code :
#OneToMany(mappedBy = "courseEntity")
private List<CourseMaterialEntity> courseMaterialEntityList;
With :
#OneToMany(fetch = FetchType.EAGER, mappedBy = "courseEntity", cascade = CascadeType.ALL)
private List<CourseMaterialEntity> courseMaterialEntityList;
You need to change #OneToMany(mappedBy = "courseEntity") to #OneToMany(mappedBy = "courseEntity", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
The default fetch type is lazy so when you try and access the collection it hasn't been loaded from the database.
Related
Going further into Hibernate i've stumbled upon the following situation:
I have an #Entity Person
#Entity
#Table(name = "PERSON")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
#DiscriminatorValue(value="person")
public class Person implements PersonInterface{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USER_ID")
protected Integer id;
#Column(name = "NAME")
protected String name;
#ElementCollection
#Formula("(SELECT groupId FROM PERSON_GROUPS WHERE id = id")
protected List<Integer> groups = new ArrayList<>();
#Override
public Integer getId() {
return id;
}
#Override
public Collection<Integer> getGroups(){
return groups;
}
#Override
public String getName() {
return name;
}
}
Which is split in two parts, Immutable and Mutable:
#Entity
#DiscriminatorValue("mutableperson")
#Transactional
public class MutablePerson extends Person implements MutablePersonInterface{
#Override
public void setName(String name) {
this.name = name;
}
#Override
public void setId(Integer id) {
this.id = id;
}
#Override
public void setGroups(List<Integer> groupIds) {
this.groups = groupIds;
}
public void excludeFromGroup(Integer groupId){
Hibernate.initialize(this.groups);
this.groups.remove(groupId);
}
}
Now, when i try to call something like:
Session session = sessionFactory.openSession();
MutablePerson personFromDb = (MutablePerson) personService.getMutablePersonById(0);
personFromDb.excludeFromGroup(group1.getId());
session.saveOrUpdate(personFromDb);
I get an exception:
Exception in thread "main" org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.internal.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:704)
at org.hibernate.Hibernate.initialize(Hibernate.java:65)
at com.studytrails.tutorials.springhibernatejpa.MutablePerson.excludeFromGroup(MutablePerson.java:57)
at com.studytrails.tutorials.springhibernatejpa.TestSpringHibernateJpa.main(TestSpringHibernateJpa.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Which tells me, that #Transactional annotation for that MutablePerson class doesn't really work and Hibernate is not creating a transaction.
Here's this bit of my spring configuration:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
As far as i can tell from Hibernate docs and examples, this config is correct and it should work, but it doesn't. Am i missing yet another Hibernate nuance here?
P.S. I know i could've done this in DAO or Service class, but unfortunately i'm bound to use existing API, which works with groups in the mutable half of the entity.
Entities are not managed by Spring. they are created as a product of database operation via hibernate or manually to save date. therefore the #Transactional annotation will not work as this is not a spring managed bean.
Spring transactional context wraps around a spring managed bean and act on it. it cannot wrap non spring beans
Possible Solution
Move the transactional context ideally for service layer or at least Jpa Repository/Dao layer.
I'm trying to learn Spring Data JPA with Hibernate, currently within a Java standalone project (though later I'll use things within a Web Project), and I'm getting the exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.dbprototype.domain.Crash.vehicles
And I'm not sure why.
#Entity(name = "STAGING.TEST_CRASH")
public class Crash {
#Id
#Column(name = "C_TEST_CRASH_NUMBER")
private int crashNum;
#Column(name = "C_RECORD_NUMBER")
private int recordNum;
#Column(name = "C_TOTAL_UNITS")
private int totalUnits;
#Column(name = "C_TOTAL_INJURIES")
private int totalInjured;
#OneToMany(cascade=CascadeType.ALL, mappedBy="crash") // fails.
private List<Vehicle> vehicles;
#OneToOne(mappedBy="crash", cascade=CascadeType.ALL) // this works ok.
private Metadata metaData;
public void printCrash() {
// prints Crash fields, vehicles, and metadata.
}
// getters & setters
}
#Entity(name = "STAGING.TEST_VEHICLE")
public class Vehicle {
#Id
#Column(name = "V_TEST_VEHICLE_NUMBER")
private int vehicleNum;
//#Id
#Column(name = "C_TEST_CRASH_NUMBER")
private int crashNum;
#Column(name = "C_RECORD_NUMBER")
private int recordNum;
#Column(name = "V_VEH_MAKE")
private String vehicleMake;
#Column(name = "V_VEH_MODEL")
private String vehicleModel;
#Column(name = "V_VEH_YEAR")
private int year;
#ManyToOne(cascade=CascadeType.ALL)
private Crash crash;
// getters & setters
}
My Service Layer is:
#Service
#Transactional(propagation=Propagation.REQUIRED)
public class CrashService {
private CrashDao crashDao;
public void setCrashDao(CrashDao dao) {
crashDao = dao;
}
public void print() {
System.out.println("you called CrashService!");
}
// DAO layer will need all 4 CRUD operations on each table.
// read one Crash
public Crash readCrash(int id) {
return crashDao.findOne(1000);
}
And my DAO layer is just:
#Repository
public interface CrashDao extends CrudRepository<Crash, Integer>{ }
My spring.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
">
<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans -->
<context:component-scan base-package="com.dbprototype" />
<!-- Activates various annotations to be detected in bean classes e.g: #Autowired -->
<context:annotation-config />
<jpa:repositories base-package="com.dbprototype.dao" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- data source properties -->
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.OracleDialect" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<!-- Spring based scanning for #Entity classes -->
<property name="packagesToScan" value="com.dbprototype.domain" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
I'm not understanding the correct way to do a #OneToMany, though from some tutorials, what I have is "correct". Though if I change the #OneToMany to use EAGER loading instead of the default LAZY, I get a different exception:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "VEHICLES1_"."CRASH_C_TEST_CRASH_NUMBER": invalid identifier
Could someone help me understand what is going on, and how to do the OneToMany correctly?
Thanks
Chris
Does that relation works in the other way? If you'd like to access the Crash from any Vechicle?
What's the join column in the table of Vechicle? I think, you miss the #JoinColumn annotation in the class Vechicle.
See the JPA WikiBook about ManyToOnes: https://en.wikibooks.org/wiki/Java_Persistence/ManyToOne
Code:
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "join_column_in_table_of_vechicle", reverseJoinColumn="C_TEST_CRASH_NUMBER")
private Crash crash;
If not, please provide the table structures, and turn on SQL-Logging, and provide the select, which causes the exception.
I am using Spring 3.2 and Hibernate but i am getting eror of that its not allowing to create bean of SessionFacotry from the XML file i dont know why this error is coming. i have search alot but not finding exceat ans please help for the same.
Here my file is XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- For context suppport of the Controller -->
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.book.controller"></context:component-scan>
<!-- For enable the MVC Support -->
<!-- <mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/"></mvc:resources>
-->
<!-- Enabling the suppot the UI user side -->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- For messages for the Labels -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- For the Properties of JDBC -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<!--Database Properties -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<!-- Session facotry configration -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- <property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property> -->
<property name="packagesToScan" value="com.book.bookentity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- implementation bean config. -->
<bean id="autherMasterServiceInterfacecontroller" class="com.book.service.AutherMasterServiceInterfaceImpl"></bean>
<bean id="bookMasterServiceInterfacecontroller" class="com.book.service.BookMasterServiceInterfaceImpl"></bean>
<bean id="emailMasterInterfacecontroller" class="com.book.service.EmailMasterInterfaceImpl"></bean>
<bean id="languageMasterinterfacecontroller" class="com.book.service.LanguageMasterinterfaceimpl"></bean>
<bean id="bookMasterInterface" class="com.book.bookDao.BookMasterInterfaceImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="emailMasterInterface" class="com.book.bookDao.EmailMasterInterfaceImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="languageMasterInterface" class="com.book.bookDao.LanguageMasterInterfaceImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="autherMasterInterface" class="com.book.bookDao.AutherMasterInterfaceImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<!-- Enabling transction managar -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Config Tranaction Managar -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
</beans>
bean class1
#Entity
#Table(name = "tbl_bookmaster", uniqueConstraints = { #UniqueConstraint(columnNames = "bid") })
public class BookMasterTable {
#Id
#GeneratedValue
#Column(name = "bid")
private int bookid;
#Column(name = "bookname")
private String bookname;
#Column(name = "booktype")
private String booktype;
#Column(name = "bookprice")
private String bookprice;
#Column(name = "bestsaler")
private int bestsaller;
#ManyToOne
#JoinColumn(name = "lid")
private LanguageMasterTable languageMasterTable;
#ManyToOne
#JoinColumn(name = "auid")
private AutherMasterTable autherMasterTable;
#ManyToOne
#JoinColumn(name = "mailid")
private EmailMasterTable emailMasterTable;
// getter and setter
}
bean2
#Entity
#Table(name = "tbl_contactmaster")
public class EmailMasterTable implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#OneToMany
#JoinColumn(name = "authercontactmail")
private Set<BookMasterTable> bookMasterTables;
#Column(name = "emailcontact")
private String emailcontact;
}
bean 3
#Entity
#Table(name = "tbl_authermaster")
public class AutherMasterTable {
#Id
#GeneratedValue
#OneToMany
#JoinColumn(name = "auid")
private Set<BookMasterTable> bookMasterTables;
#Column(name = "authername")
private String authername;
// getter and setter
}
bean 4
public class LanguageMasterTable {
#Id
#GeneratedValue
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "language")
private Set<BookMasterTable> bookMasterTables;
#Column(name = "languagename")
private String languagename;
// getter and setter
}
controller bean
#Controller
public class BookMasterController {
#Autowired
private BookMasterServiceInterface bookMasterServiceInterfacecontroller;
#RequestMapping(value="/addbook",method= RequestMethod.POST)
public String addAuther(#ModelAttribute("book") BookMasterTable bookMasterTable){
bookMasterServiceInterfacecontroller.addBook(bookMasterTable);
return "bookadded";
}
}
like that having all controller for each bean class
service interface
public interface BookMasterServiceInterface {
public void addBook(BookMasterTable bookMasterTable);
}
service calss
#Service
public class BookMasterServiceInterfaceImpl implements BookMasterServiceInterface{
#Autowired
private BookMasterInterface bookMasterInterface;
#Override
#Transactional
public void addBook(BookMasterTable bookMasterTable) {
// TODO Auto-generated method stub
bookMasterInterface.addBooks(bookMasterTable);
}
}
like that having service for all bean
Repository class interface
public interface BookMasterInterface {
public void addBooks(BookMasterTable bookMasterTable);
}
repository class implementation having for each bean
#Repository
public class BookMasterInterfaceImpl implements BookMasterInterface {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addBooks(BookMasterTable bookMasterTable) {
// TODO Auto-generated method stub
try {
sessionFactory.getCurrentSession().save(bookMasterTable);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
and what error i am getting is.
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.book.service.BookMasterServiceInterface com.book.controller.BookMasterController.bookMasterServiceInterfacecontroller; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookMasterServiceInterfacecontroller': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.book.bookDao.BookMasterInterface com.book.service.BookMasterServiceInterfaceImpl.bookMasterInterface; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookMasterInterface': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.book.bookDao.BookMasterInterfaceImpl.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/BookServletmvc-servlet.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
... 20 more
main this is that is not allowing to create because its getting null pointer but i dont know where here.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/BookServletmvc-servlet.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
... 48 more
Caused by: java.lang.NullPointerException
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:538)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:126)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1514)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1437)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1355)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1724)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1775)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:247)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:373)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 58 more
i will be happy if u can help :)
i have four entities. first one is
#Entity
#Table(name = "tbl_bookmaster", uniqueConstraints = { #UniqueConstraint(columnNames = "bid") })
public class BookMasterTable {
#Id
#GeneratedValue
#Column(name = "bid")
private int bookid;
#Column(name = "bookname")
private String bookname;
#Column(name = "booktype")
private String booktype;
#Column(name = "bookprice")
private String bookprice;
#Column(name = "bestsaler")
private int bestsaller;
#ManyToOne
#JoinColumn(name = "lid")
private LanguageMasterTable languageMasterTable;
#ManyToOne
#JoinColumn(name = "auid")
private AutherMasterTable autherMasterTable;
#ManyToOne
#JoinColumn(name = "mailid")
private EmailMasterTable emailMasterTable;
public int getBookid() {
return bookid;
}
public void setBookid(int bookid) {
this.bookid = bookid;
}
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public String getBooktype() {
return booktype;
}
public void setBooktype(String booktype) {
this.booktype = booktype;
}
public String getBookprice() {
return bookprice;
}
public void setBookprice(String bookprice) {
this.bookprice = bookprice;
}
public int getBestsaller() {
return bestsaller;
}
public void setBestsaller(int bestsaller) {
this.bestsaller = bestsaller;
}
public LanguageMasterTable getLanguageMasterTable() {
return languageMasterTable;
}
public void setLanguageMasterTable(LanguageMasterTable languageMasterTable) {
this.languageMasterTable = languageMasterTable;
}
public AutherMasterTable getAutherMasterTable() {
return autherMasterTable;
}
public void setAutherMasterTable(AutherMasterTable autherMasterTable) {
this.autherMasterTable = autherMasterTable;
}
public EmailMasterTable getEmailMasterTable() {
return emailMasterTable;
}
public void setEmailMasterTable(EmailMasterTable emailMasterTable) {
this.emailMasterTable = emailMasterTable;
}
}
I think the problem is here, in AutherMasterTable (and similar places in other entities):
#Id
#GeneratedValue
#OneToMany
#JoinColumn(name = "auid")
private Set<BookMasterTable> bookMasterTables;
For a one-to-many join, the join column mentioned in the JoinColumn annotation is in the other table. It does not refer to a column in this table. Besides, a Set cannot be an identifier.
Try using two fields instead:
#Id
#GeneratedValue
#Column(name = "auid")
private int autherId;
#OneToMany
#JoinColumn(name = "auid")
private Set<BookMasterTable> bookMasterTables;
Note that we are not defining the same column twice in the same table: the first mention of auid above refers to a column in tbl_authermaster and the second one refers to the auid column in tbl_bookmaster.
Despite your mistake, Hibernate should not be throwing a NullPointerException at you. That is a bug in Hibernate.
Reading the stacktrace, you know where:
java.lang.NullPointerException
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:538)
at ...
You should run in debug with a breakpoint at that line, but I'd think that basically means you have an error in your entity, your mapping or on the database it's run on. If you can, you should generate the schema with Hibernate, then you should compare the difference between your target schema and the generated schema => that would print the mapping error.
Also there are no mappedBy on your OneToMany and ManyToOne. You should check that first (it is not an error to not have them, but it might become a problem if the database schema is not in sync with Hibernate expected schema).
I am creating a backend application using Spring, Hibernate and JPA.
Currently the application test pass but I get a warning:
WARN: HHH000436: Entity manager factory name (JpaPersistenceUnit) is already registered.
I think the reason for this is that I defined my JpaPersistenceUnit in the persistence.xml and I also create one in my dao class. If this is the case I need to find a way to get my JpaPersistenceUnit from the persistence.xml without creating it (again). But I don't know how...
This is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="JpaPersistenceUnit"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value="groepD"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/groepd"/>
<property name="hibernate.connection.username" value="groepD"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
This is my generic dao class:
public interface GenericDao<E, ID extends Serializable> {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JpaPersistenceUnit");
public void add(E entity);
public void remove(E entity);
public void update(E entity);
public E findById(ID id);
public List<E> findAll();
}
This is the specific dao class:
public interface TripDao extends GenericDao<Trip,Integer> {
}
And this is an implementation of the dao class:
#Repository
public class TripDaoImpl implements TripDao {
protected EntityManager entityManager;
public TripDaoImpl() {
entityManager = emf.createEntityManager();
}
#Override
#Transactional
public void add(Trip entity) {
entityManager.getTransaction().begin();
entityManager.persist(entity);
entityManager.getTransaction().commit();
}
....
}
This is the entity:
#Entity
#Table(name = "T_TRIP")
public class Trip {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotNull
private String name;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="T_TRIP_ADMINS",
joinColumns={#JoinColumn(name="tripId")},
inverseJoinColumns={#JoinColumn(name="userId")})
private Set<User> admins;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="T_TRIP_PARTICIPANT",
joinColumns={#JoinColumn(name="tripId")},
inverseJoinColumns={#JoinColumn(name="userId")})
private Set<User> invitedUsers;
#NotNull
private Boolean privateTrip;
#NotNull
private Boolean published;
#Enumerated(EnumType.STRING)
private TripType type;
#NotNull
private Integer nrDays;
#NotNull
private Integer nrHours;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "tripId")
private Set<Stop> stops;
public Trip(){
initLists();
}
private void initLists(){
this.admins = new HashSet<User>();
this.invitedUsers = new HashSet<User>();
this.stops = new HashSet<Stop>();
}
public void addStop(Stop stop) {
stops.add(stop);
}
public boolean removeStop(Stop stop) {
if (stops.size() > 1 && stops.contains(stop)) {
stops.remove(stop);
return true;
} else {
return false;
}
}
...More getters and setters...
}
If someboby could tell me how to to fix the warning that would be very helpfull.
first: (in you applicationContext.xml)
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation"
value="classpath:persistence.xml">
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
<property name="loadTimeWeaver"> <!-- 运行时植入 -->
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
next:(update you code)
remove :EntityManagerFactory emf = Persistence.createEntityManagerFactory("JpaPersistenceUnit");
next: you can get the class EntityManager by this
#PersistenceContext
protected EntityManager entityManager;
ps:sorry my english is so poor,
wish helpfull for you!
I have a problem with lazy initialisation. I can't find a solution.
Exception:
[pool-1-thread-12] ERROR:12:20:14.840 o.h.LazyInitializationException - failed to lazily initialize a collection of role: de.beeld.forges.domain.Server.applications, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: de.beeld.forges.domain.Server.applications, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
[pool-2-thread-1] ERROR:12:20:14.840 o.s.s.support.MethodInvokingRunnable - Invocation of method 'readStatusCache' on target class [class de.beeld.forges.task.annotation.ScheduledProcessor$$EnhancerByCGLIB$$ee649dc3] failed
java.util.ConcurrentModificationException: null
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
hibernate.xml
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="standardDataSource" p:lobHandler-ref="defaultLobHandler">
<property name="annotatedClasses">
<list>
<value>de.beeld.forges.domain.Server</value>
<value>de.beeld.forges.domain.Application</value>
<value>de.beeld.forges.domain.Forge</value>
</list>
</property>
</property>
</bean>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Read in DAOs from the hibernate package -->
<context:component-scan base-package="de.beeld.forges.dao" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="de.beeld">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
<context:exclude-filter expression="org.springframework.stereotype.Repository"
type="annotation" />
</context:component-scan>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
readStatusCache method:
public void readStatusCache() {
String execCommand = "java -jar ...";
List<Future<Map<Long, Integer>>> list = new ArrayList<Future<Map<Long, Integer>>>();
String serverName = null;
for (Server server : serviceFacade.getServers()) {
serverName = server.getName();
Callable<Map<Long, Integer>> worker = new ApplicationStatusReader2(server.getApplications(),
sshConnector, execCommand, serverName);
Future<Map<Long, Integer>> submit = this.serviceFacade.getExecutor().submit(worker);
list.add(submit);
}
for (Future<Map<Long, Integer>> future : list) {
//do stuff
}
}
Server.java
#Entity
#org.hibernate.annotations.Entity(dynamicUpdate = true)
public class Server implements DomainObject, Comparable<Server> {
private static final long serialVersionUID = -8920952435734596243L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true, nullable = false)
#NotEmpty
private String name;
#Column(nullable = false)
#NotEmpty
#Pattern(regexp = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$", message = "The ip must be in format xxx.xxx.xxx.xxx")
private String ip;
#Column(nullable = false)
#NotEmpty
private String fqdn;
#OneToMany(mappedBy = "server", fetch = FetchType.LAZY)
private List<Application> applications;
#Version
private int version;
//getter and setter
}
Application.java
#Entity
public class Application implements DomainObject {
private static final long serialVersionUID = -8127137156319959239L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
private Server server;
#Column(nullable = false)
#NotEmpty
private String name;
#Column(nullable = false)
#NotEmpty
private String location;
#Column(nullable = false)
#NotEmpty
private String binDir;
private String confDir;
private boolean isContainer = false;
private String containerDir;
private String startup = "startup.sh";
private String shutdown = "shutdown.sh";
#ManyToOne(fetch = FetchType.LAZY)
#Fetch(FetchMode.JOIN)
private Forge forge;
#ManyToOne(fetch = FetchType.LAZY)
#Fetch(FetchMode.JOIN)
private Application parent;
#OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<Application> offsprings;
#NotEmpty
private String blueprint;
private Integer replaceable = 0;
private Integer running = 0;
#Version
private int version;
//getter and setter
}
I don't really know why I cant read the list of applications from the server
If anybody could help it would be great.
Most likely because you're setting applications collection to lazy load. So when you return from the initial call to serviceFacade.getServers(), my guess is that you no longer have the session opened that was used to fetch the list of servers.
As a result, when you iterator through the applications, the session was closed, so it can't load the actual contents of the collection.
You have three possibilities:
Keep the session open (google for binding hibernate session to thread, or if the readStatusCache method is in a spring managed object, just add an #Transactional annotation to it, or the entry point from which it is called).
Change the applications collection to be an eager load
have your dao layer fully initialize the applications collection (see Hibernate.initialize method) while the session is still open.
The two loops
for (Server server : serviceFacade.getServers()) {
serverName = server.getName();
Callable<Map<Long, Integer>> worker = new ApplicationStatusReader2(server.getApplications(),
sshConnector, execCommand, serverName);
Future<Map<Long, Integer>> submit = this.serviceFacade.getExecutor().submit(worker);
list.add(submit);
}
for (Future<Map<Long, Integer>> future : list) {
//do stuff
}
are being called by two separate threads simultaneously. You can check if this is the case by synchronizing the readStatusCache() method. But this should be done in the Spring layer. Are you using transactions etc. properly?
Please read this answer for more on thread safety with spring and hibernate. Spring-Hibernate used in a webapp,what are strategies for Thread safe session management
When I got the same exception, the solution was to add the #Transactional annotation to the method in the controller.