EclipseLink JPA Unknown entity bean class - java

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?

Related

How to get rid of 'java.lang.IllegalArgumentException: Unknown entity' while running a hibernate app?

I am new to Hibernate and while creating a small app using it I got following exception (error is related with persist of EntityManager):
java.lang.IllegalArgumentException: Unknown entity: com.nataniel.api.domain.User
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:840)
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 org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at com.sun.proxy.$Proxy993.persist(Unknown Source)
at com.nataniel.api.services.UserService.createUser(UserService.java:29)
Can anybody please help me out?
The Entity class is as follows:
Entity User:
package com.nataniel.api.domain;
import org.hibernate.annotations.Entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="USER")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name = "LOGIN")
private String login;
#Column(name = "NAME")
private String name;
#Column(name = "EMAIL")
private String email;
#Column(name = "PASSWORD")
private String password;
#Column(name = "CITY")
private String city;
#Column(name = "REGION")
private String region;
#Column(name = "BIRTHDATE")
private String birthDate;
public User() {
}
public User(String login, String name, String email, String password, String city, String region, String birthDate) {
this.login = login;
this.name = name;
this.email = email;
this.password = password;
this.city = city;
this.region = region;
this.birthDate = birthDate;
}
// getters and setters
}
DAO file:
package com.nataniel.api.services;
import org.apache.camel.Exchange;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import com.nataniel.api.domain.User;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
#Service("userService")
public class UserService {
#PersistenceContext
transient EntityManager entityManager;
#Transactional
public String createUser(Exchange exchange) {
JSONObject userAccountJSON = (JSONObject) exchange.getIn().getHeader("jsonRequest");
User user = new User();
user.setLogin(userAccountJSON.getString("login"));
user.setEmail(userAccountJSON.getString("email"));
user.setPassword(userAccountJSON.getString("password"));
user.setName(userAccountJSON.getString("name"));
user.setCity(userAccountJSON.getString("city"));
user.setRegion(userAccountJSON.getString("region"));
user.setBirthDate(userAccountJSON.getString("birthdate"));
entityManager.persist(user);
return userAccountJSON.toString();
}
}
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
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_1_0.xsd"
version="1.0">
<persistence-unit name="service-provider" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.nataniel.api.domain.User</class>
<properties>
<!-- propriedades do hibernate -->
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<!-- atualiza o banco, gera as tabelas se for preciso -->
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- CXF -->
<cxf:rsServer id="user" address="/userservice"
serviceClass="com.nataniel.api.UserServiceRest"></cxf:rsServer>
<context:component-scan base-package="com.nataniel"/>
<!-- Camel -->
<bean id="routeBuilder" class="com.nataniel.api.camel.MailServiceRouteBuilder"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="routeBuilder"/>
</camelContext>
<!-- Persistence -->
<bean id="mysqlDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.0.140:3306/service-provider"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mysqlDataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="mysqlDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="false"/>
try to add this in your Entity User.
#Entity
#javax.persistence.Entity; // add this <--
#Table(name="USER")
I think your User Entity is not located because it reaches the hibernate API Entity and not the persistence Entity.

Lazy loading exception with Spring Data JPA and Hibernate

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.

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.

How do I create an instance of my EntityManagerFactory by using my persistence.xml?

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!

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