Lazy loading exception with Spring Data JPA and Hibernate - java

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.

Related

EclipseLink JPA Unknown entity bean class

I have an entity class Author
#Entity
#Table(name = "author")
public class Author implements Serializable {
private static final long serialVersionUID = -1117370177012369440L;
#Id
#GeneratedValue
#Column(name = "author_id")
private Long id;
#NotNull
#Size(max = 30)
#Column(name = "author_name")
private String name;
#Column(name = "expired")
private Date expired;
#OneToMany
#JoinTable(
name="news_author",
joinColumns={ #JoinColumn(name="author_id", referencedColumnName="author_id") },
inverseJoinColumns={ #JoinColumn(name="news_id", referencedColumnName="news_id", unique=true) }
)
private Set<News> news;
}
And the News:
#Entity
#Table(name = "news")
public class News implements Serializable {
private static final long serialVersionUID = -2401617129682260390L;
#Id
#GeneratedValue
#Column(name = "news_id")
private Long id;
#NotNull
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "creation_date")
private Date creationDate;
#ManyToOne
private Author author;
}
That is my persistence.xml:
<?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="newsmanagement" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.newsmanagement.domain.Author</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="javax.persistence.jdbc.user" value="TEST"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="eclipselink.weaving" value="false"/>
</properties>
That is my spring-context configuration:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.newsmanagement" />
<!-- Add JPA support -->
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"/>
</property>
<property name="persistenceUnitName" value="newsmanagement" />
</bean>
<!-- Add Transaction support -->
<bean id="tx-manager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
<!-- Use #Transaction annotations for managing transactions -->
<tx:annotation-driven transaction-manager="tx-manager" />
<bean id="jpaDialect"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect " />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor "/>
</beans>
Then in the DAO class I'd like to find author by id:
#Repository
public class AuthorDAOImpl implements AuthorDAO {
#PersistenceContext
private EntityManager entityManager;
#Override
public Author findById(Long id) {
return entityManager.find(Author.class, id);
}
}
Instead of that I get the following exception:
java.lang.IllegalArgumentException: Unknown entity bean class: class com.newsmanagement.domain.Author, please verify that this class has been marked with the #Entity annotation.
There is everything ok with the annotation on the Author class. The annotation is from the org.eclipse.persistence, that I've already included via maven.
Where is the problem?

Google genericdao framework performing unnecessary selects with Maven, Spring and Hibernate

I am using Hibernate 4.2.11 Final, Spring 3.2.4 and Google Genericdao 1.2.0:
My SpringConfig.xml is:
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- Specifying that this project is using annotation based Dependency Injection or IOC -->
<context:annotation-config />
<context:component-scan base-package="com.company" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#//URL:PORT/SERVICENAME" />
<property name="username" value="ID" />
<property name="password" value="Password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.company.client.hibernate.domain.Te</value>
<value>com.company.client.hibernate.domain.TeComment</value>
<value>com.company.client.hibernate.domain.TeReason</value>
<value>com.company.client.hibernate.domain.TeStatus</value>
<value>com.company.client.hibernate.domain.TeType</value>
<value>com.company.client.hibernate.domain.TeTypeToReasonMapping</value>
</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>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<aop:aspectj-autoproxy />
</beans>
I have two tables: Reasons and Comments.
The reasons table has 3 columns:
ID - Is the PK populated using a sequence.
Code - Has a unique constraint against it and is a varchar field.
Description - varchar with text
The comments table has 4 columns:
ID - Is the PK populated using a sequence.
ReasonCode - Has a FK with the reasons table.
Order - Integer - has a unique constraint with it and reason code.
Comment - varchar with text
I am using annotations for both Hibernate and Spring.
My Reason Domain object has
private BigDecimal reasonId;
private String reasonCode;
private String reasonDescription;
private List<TeComment> comments;
#Column(name = "REASON_ID", unique = true, nullable = false, precision = 22, scale = 0)
public BigDecimal getReasonId() {
#Column(name = "REASON_CODE", unique = true, nullable = false, length = 20)
public String getReasonCode() {
#Column(name = "REASON_DESCRIPTION", nullable = false, length = 1024)
public String getReasonDescription() {
#OneToMany (mappedBy = "reason")
public List<TeComment> getComments() {
My Comments Domain object has:
private BigDecimal commentId;
private String commentDescription;
private String reasonCode;
private BigDecimal commentOrder;
private TeReason reason;
#Column(name = "COMMENT_ID", unique = true, nullable = false, precision = 22, scale = 0)
public BigDecimal getCommentId() {
#Column(name = "REASON_CODE", nullable = false, length = 20, insertable=false, updatable=false)
public String getReasonCode() {
#Column(name = "COMMENT_DESCRIPTION", nullable = false, length = 1024)
public String getCommentDescription() {
#Column(name = "COMMENT_ORDER", nullable = false, precision = 22, scale = 0)
public BigDecimal getCommentOrder() {
#ManyToOne
#JoinColumn(name = "REASON_CODE", referencedColumnName = "REASON_CODE")
public TeReason getReason() {
I am also creating a business service layer and creating test scripts for it. Two methods in the business service layer are:
public List<ReasonDTO> retrieveAllReasonsAsDTO();
public List<CommentDTO> retrieveAllCommentsAsDTO();
They are implemented as:
#Autowired
private TeCommentDAO teCommentDao;
#Autowired
private TeReasonDAO teReasonDao;
#Override
#Transactional (propagation=Propagation.REQUIRED, readOnly = true)
public List<ReasonDTO> retrieveAllReasonsAsDTO() {
return ConvertDomainDTO.convertTeReasonDomainToDTO_List(teReasonDao.findAll());
} // retrieveAllReasonsAsDTO
#Override
#Transactional (propagation=Propagation.REQUIRED, readOnly = true)
public List<CommentDTO> retrieveAllCommentsAsDTO() {
Search search = new Search(TeComment.class);
search.addFetch("reason");
List<TeComment> list = teCommentDao.search(search);
return ConvertDomainDTO.convertTeCommentDomainToDTO_List(list);
} // retrieveAllCommentsAsDTO
My JUNIT test is:
List<ReasonDTO> allReasons = businessService.retrieveAllReasonsAsDTO();
assertEquals(allReasons.size(), beginningReasonSize);
List<CommentDTO> allComments = businessService.retrieveAllCommentsAsDTO();
assertEquals(allComments.size(), beginningCommentSize);
I am having an issue where hibernate is ignoring the inner join dictated by the "addFetch" and is retrieving all the reasons individually. I sort of have it solved, but don't understand why it is working this way.
There are two solutions:
I change the order of the test script. So instead of retrieving AllReasons first, I retrieve AllComments first and then allReasons. In this case the inner join is honored and the reasons are not retrieved individually.
I change the transaction propagation from REQUIRED to REQUIRES_NEW on the Comments business method. In this case the inner join is honored and the reasons are not retrieved individually.
Clearly the issue has to do with sharing a transaction and the order of the retrieve, but I am not sure why. Does anyone have some insight for me?
Thanks a lot.

Getting Error of Error creating bean with name 'bookMasterController': Injection of autowired dependencies failed;

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).

Do i have a Hibernate cache or mapping error?

I'm using following Frameworks:
Hibernate 4.2.0.Final
Spring 3.2.2.RELEASE
Spring Data Jpa 1.1.0.RELEASE
HSQL 2.2.9
TestNG 6.1.1
I've got 2 Entities:
Entity A:
#Entity
#Table( name = "A" )
public class A {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
#OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "a" )
private Set<B> b = new HashSet<B>();
//... getter and setter
}
and Entity B:
#Entity
#Table( name = "B" )
public class B {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
#ManyToOne
#JoinColumn( name = "a_id" )
private A a;
//... getter and setter
}
And i made Spring Data JPARepositories for them:
#Repository
public interface ARepository
extends JpaRepository<A, Long> {
}
#Repository
public interface BRepository
extends JpaRepository<B, Long> {
}
Then i've wrote a test to see if the mapping works:
#TransactionConfiguration( defaultRollback = true )
#ContextConfiguration
public class ARepositoryTest
extends AbstractTransactionalTestNGSpringContextTests {
#Inject
#Setter
private ARepository aRepository;
#Inject
#Setter
private BRepository bRepository;
#Test( groups = { "integration" } )
public void testSaveWithFeed() {
A a = new A();
aRepository.saveAndFlush( a );
B b = new B();
b.setA( a );
bRepository.saveAndFlush( b );
A findOne = aRepository.findOne( a.getId() );
Assert.assertEquals( 1, findOne.getB().size() );
}
}
But the test fails:
Hibernate: insert into A (id) values (default)
Hibernate: insert into B (id, a_id) values (default, ?)
FAILED: testSaveWithA
java.lang.AssertionError: expected [1] but found [0]
And i don't see why. Is there something missing in the mapping, or is do i have to clear a hibernate cache?
I see that there is no new select-query so hibernate is caching the A object - but shouldn't it update the reference from A to the Bs in it's cache??
As additional info here's my persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="local" transaction-type="RESOURCE_LOCAL" >
</persistence-unit>
</persistence>
My ARepositoryTest-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="my.package"/>
<import resource="classpath:/SpringBeans.xml"/>
</beans>
and my SpringBeans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
<context:annotation-config />
<jpa:repositories base-package="my.package.dao" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="local"/>
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"/>
<property name="database" value="HSQL" />
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.show_sql" value="true" />
</map>
</property>
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:file:${user.home}/data;shutdown=true" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
edit: added version numbers, and xml files
edit: for JB Nizet answer
If i add to Class A
public void addB( B b ) {
this.b.add( b );
}
and adapt the testcase
#Test( groups = { "integration" } )
public void testSaveWithA() {
A a = new A();
aRepository.save( a );
B b = new B();
a.addB( b );
aRepository.saveAndFlush( a );
A findOne = aRepository.findOne( a.getId() );
Assert.assertEquals( findOne.getB().size(), 1 );
}
the test passes
But within the hsql file there is no link between A and B:
INSERT INTO A VALUES(1)
INSERT INTO B VALUES(1,NULL)
So it won't be able to select it correct in an other transaction.
If i expand the new mMethod in A
public void addB( B b ) {
this.b.add( b );
b.setA( this );
}
An exception occures when flushing or committing
java.lang.StackOverflowError
at java.util.HashMap$KeyIterator.<init>(HashMap.java:926)
at java.util.HashMap$KeyIterator.<init>(HashMap.java:926)
at java.util.HashMap.newKeyIterator(HashMap.java:940)
at java.util.HashMap$KeySet.iterator(HashMap.java:974)
at java.util.HashSet.iterator(HashSet.java:170)
at java.util.AbstractSet.hashCode(AbstractSet.java:122)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:429)
at my.package.A.hashCode(A.java:17)
at my.package.B.hashCode(B.java:13)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:429)
at my.package.A.hashCode(A.java:17)
at my.package.B.hashCode(B.java:13)
...
Linenumbers A.java:17 and B.java:13 is where the #Data annotation of Lombok is placed generating my getters and setters.
Resolved by removing the dependency to lombok for hashCode and equals / by using Lomboks #EqualsAndHashCode( exclude = { "b" } )
Your test runs in a single transaction, using a single session. So when you're executing aRepository.findOne(a.getId()), Hibernate returns the A that is already in its first level cache. And since you forgot to add the B to the set of Bs in A, this set is still empty.
It's your responsibility to maintain the coherence of the object graph. If you do b.setA(a), you should also do a.getBs().add(b). The best way is to encapsulate these two operations into a method addB(B b) in A, which adds the B to the set and initializes B.a.

Spring #Transactional not inserting into table

I am having trouble saving data into the database. I can see the insert SQL statement in the logs and also I write the generated ID to the log. The problem I am facing is the data is not being persisted into the database from the session.
I don't have any trouble fetching the data from the database. The user I am using has read/write access to the database and also I don't get any errors.
I am using Spring 4.2.3, Hibernate 5.5.0, MySQL 5 and Primefaces 5.3.
I search all the forums and found nothing that helped me.
Has anybody faced similar issues?
Model
#Entity
#Table(name = "borrower", uniqueConstraints = {
#UniqueConstraint(columnNames = "borrower_id")
})
public class Borrower implements java.io.Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "borrower_id", unique = true, nullable = false)
private Integer borrowerId;
#Column(name = "borrower_code", nullable = true, length = 20)
private String borrowerCode;
#Column(name = "first_name", nullable = false, length = 45)
private String firstName;
#Column(name = "last_name", nullable = true, length = 45)
private String lastName;
#Column(name = "phone", nullable = true, length = 45)
private String phone;
#Column(name = "borrower_status", nullable = false, length = 15)
private String borrowerStatus;
#Column(name = "email_id", nullable = false, length = 200)
private String emailId;
public Borrower() {
}
// Getters and setters
}
DAO
public class BorrowerDAOImpl extends HibernateDaoSupport implements BorrowerDAO {
private final Logger logger = LogManager.getLogger(getClass());
#Autowired
private SessionFactory sessionFactory;
#Override
public boolean saveBorrower(Borrower borrower) {
try {
Session session = sessionFactory.getCurrentSession();
session.persist(borrower);
session.flush();
logger.info("Borrower '{} {}' with Borrower ID '{}' saved successfully.", borrower.getFirstName(), borrower.getLastName(), borrower.getBorrowerId());
session.disconnect();
return true;
}
catch (Exception e) {
logger.error("Unable to add new borrower '{} {}', error: ", borrower.getFirstName(), borrower.getLastName(), e);
return false;
}
}
}
Service
#Service("borrowerBO")
#SessionScoped
#Transactional(readOnly = true)
public class BorrowerBOImpl implements BorrowerBO {
#Autowired
BorrowerDAO borrowerDAO;
#Transactional(readOnly = false)
#Override
public boolean saveBorrower(Borrower borrower) {
return borrowerDAO.saveBorrower(borrower);
}
public BorrowerDAO getBorrowerDAO() {
return borrowerDAO;
}
public void setBorrowerDAO(BorrowerDAO borrowerDAO) {
this.borrowerDAO = borrowerDAO;
}
}
Spring Config
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.movielibrary.bo"/>
<!-- SessionFactory bean -->
<import resource="classpath:HibernateSessionFactory.xml"/>
<!-- Annotate transaction behaviour -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Transaction manager bean -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Bean declaration -->
<bean id="borrowerBO" class="com.movielibrary.bo.impl.BorrowerBOImpl">
<property name="borrowerDAO" ref="borrowerDAO" />
</bean>
<bean id="borrowerDAO" class="com.movielibrary.dao.impl.BorrowerDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Hibernate Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- Database configuration bean -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/test_db?relaxAutoCommit=true" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
<!-- SessionFactory bean -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- Hibernate annotations property -->
<property name="packagesToScan" value="com.movielibrary.model" />
<property name="annotatedClasses">
<list>
<value>com.movielibrary.model.Borrower</value>
</list>
</property>
</bean>
</beans>

Categories

Resources