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>
Related
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 trying to create two join tables ConceptModelDetails and Instructions using a foreign key. Following are my model classes:
ConceptModelDetails:
package com.assignment.model;
#Entity
#Table(name="conceptModelDetails")
public class ConceptModelDetails {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int instructionsId;
private String operationType;
private String conceptModelID;
private String requestor;
private String status;
private Timestamp requestDateTime;
private Timestamp lastExecutedDateTime;
private Timestamp completedDateTime;
#OneToMany(cascade=CascadeType.ALL, mappedBy="conceptModelDetails")
private Set<Instructions> instructions;
public ConceptModelDetails() {}
}
and Instuctions:
package com.assignment.model;
#Entity
#Table(name="instructions")
public class Instructions {
#Id
#GeneratedValue
private int Sno;
private String instruction;
#ManyToOne
#JoinColumn(name="instructionsId")
private ConceptModelDetails conceptModelDetails;
}
Following is applicationContext.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://192.168.1.79:5432/test" />
<property name="username" value="postgres" />
<property name="password" value="admin" />
</bean>
<bean id="objDAO" class="com.assignment.dao.impl.ConceptModelDAOImpl">
<property name="sessionFactory" ref="sessionfactory" />
</bean>
<bean id="sessionfactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="com.assignment.model"></property>
<property name="annotatedClasses">
<list>
<value>com.assignment.model.ConceptModelDetails</value>
<value>com.assignment.model.Instructions</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionfactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
and Controller:
#RequestMapping(value = "/myCntrl", method = RequestMethod.POST)
public String handler(HttpServletRequest request) {
System.out.println("handler");
// System.out.println(request.getParameter("conceptID"));
// System.out.println(request.getParameter("operationType"));
String[] operations = request.getParameterValues("operations");
Date date = new Date();
Timestamp time = new Timestamp(date.getTime());
ConceptModelDetails conceptModelDetails = new ConceptModelDetails();
conceptModelDetails
.setConceptModelID(request.getParameter("conceptID"));
conceptModelDetails.setOperationType(request
.getParameter("operationType"));
conceptModelDetails.setRequestor(request.getParameter("requestor"));
conceptModelDetails.setRequestDateTime(time);
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("yo");
ConceptModelDAO obj = (ConceptModelDAO)context.getBean("objDAO");
System.out.println("no");
Instructions instructions = new Instructions();
for(int i = 0; i < operations.length; i++){
instructions.setInstruction(operations[i]);
obj.addInstructions(instructions);
}
obj.add(conceptModelDetails);
return "success";
}
Problems when I run this code are:
Same hibernate_sequence is used for both the tables.
Foreign key is not mapped in the Instruction table as seen in the following screenshot.
Please guide what is wrong with the code. I am new to hibernate and spring, so I'd appreciate a detailed explanation. Thanks in advance.
1) You are using the Global sequence generator that hibernate provide by default when no generator is provided as specifed by the JPA Spec.
Change it as follows. Do this to the both of the classes with different sequences for each class.
#Entity
#SequenceGenerator(name="PRIVATE_SEQ", sequenceName="private_sequence")
public class ConceptModelDetails {
#Id #GeneratedValue(strategy = GenerationType.SEQUENCE, generator="PRIVATE_SEQ")
private int instructionsId;
2) Here Instructions class owns the relationship and
therefore you should set ConceptModelDetails object to the Instructions object before saving the Instructions object.
ConceptModelDetails cmd1 = new ConceptModelDetails();
Instructions i = new Instructions()
i.setConceptModelDetails(cmd1);
....
Then save the Instructions object i
Hope this helps.
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?
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.
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).