Tomcat + hibernate = no persistent classes found for query class - java

I'm developing a web app and deploying it on Tomcat 7.0. My app uses a MySQL database. I've already configured connection between app and database and wanted to add Hibernate 5.2.5 support. I can communicate with database via Hibernate console with configuration below, and it works when I use it in non-web app. The problem is only when I deploy it on server. I get warning
no persistent classes found for query class: from entities.UserH
and then 500 server error caused by it.
My entity class:
#Entity
#Table(name = "users", uniqueConstraints = {#UniqueConstraint(columnNames = {"id"})})
public class UserH {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, unique = true, length = 11)
private int id;
#Column(name = "login", nullable = false, length = 45)
private String login;
#Column(name = "name", nullable = false, length = 45)
private String name;
#Column(name = "surname", nullable = false, length = 45)
private String surname;
/* getters and setters*/
}
My hibernate-annotation.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties - Driver, URL, user, password -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/web-database</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Mapping with model class containing annotations -->
<mapping class="entities.UserH"/>
</session-factory>
</hibernate-configuration>
Method that should get users:
public List<UserH> getAllUsers() {
try (Session session = HibernateUtils.getSessionAnnotationFactory().getCurrentSession()) {
session.beginTransaction();
Query<UserH> usersQuery = session.createQuery("from entities.UserH", UserH.class);
List<UserH> usersList = usersQuery.getResultList();
session.getTransaction().commit();
return usersList;
}
}
As I mentioned - it works ok with normal app, but not with Tomcat. I added all available elements to web artifacts, but it didn't help. I even tried to add JPA support with persistance.xml, but still with no luck.
What else could be the problem?
edit: My HibernateUtils class:
public class HibernateUtils {
private static SessionFactory sessionAnnotationFactory;
private static SessionFactory buildSessionAnnotationFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate-annotation.cfg.xml");
System.out.println("Hibernate Annotation Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
System.out.println("Hibernate Annotation serviceRegistry created");
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionAnnotationFactory() {
if (sessionAnnotationFactory == null)
sessionAnnotationFactory = buildSessionAnnotationFactory();
return sessionAnnotationFactory;
}
}

Maybe this is not a proper answer fot my question, but this is what actually worked for me. I replaced hibernate with JPA configuration + hibernate.
So instead of using hibernate-annotation.cfg.xml + Session I used persistance.xml + EntityManager:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="NewPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>entities.UserH</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/web-database"/>
<property name="javax.persistence.jdbc.user" value="Admin"/>
<property name="javax.persistence.jdbc.password" value="password2#"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
getEntityManager:
public static EntityManager getEntityManager() {
EntityManager entityManager = Persistence
.createEntityManagerFactory("NewPersistenceUnit")
.createEntityManager();
return entityManager;
}
getAllUsers:
public List<UserH> getAllUsers() {
EntityManager entityManager = HibernateUtils.getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
TypedQuery<UserH> usersQuery = entityManager.createQuery("from UserH ", UserH.class);
List<UserH> usersList = usersQuery.getResultList();
transaction.commit();
entityManager.close();
return usersList;
}
However, I still don't understand why this configurations works while hibernate alone didn't. Any comments/suggestions would be appreciated.

You should just change your query to reference only the class name:
session.createQuery( "FROM UserH", UserH.class )
The only time the package is important would be when you're defining entities as inner classes.
For those cases, you'd need to use the full class name, com.c.SomeOutterClass$MyEntity. Another alternative is to change the #Entity annotation so that it includes the name attribute so you explicitly name your entity class:
public class SomeOutterClass {
#Entity(name = "MyEntity")
public static class MyEntity {
}
}

Related

mapping java enum with hibernate to postges

i want to create and add to database user with enum
but cannot create instance
Required type:javax.management.relation.Role
Provided: cinema.entity.Role
how to fix it
user class
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String login;
private String password;
#Enumerated(EnumType.STRING)
#Column(name = "role")
private Role role;
}
enum
public enum Role {
USER, MANAGER, ADMIN
}
db
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:postgresql://localhost:5432/cinema</property>
<property name="connection.username">user</property>
<property name="connection.password">user</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL10Dialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping class="cinema.entity.User"/>
<mapping class="cinema.entity.Film"/>
<mapping class="cinema.entity.Ticket"/>
<mapping class="cinema.entity.Role"/>
<!-- DB schema will be updated if needed -->
<!-- <property name="hibernate.hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>
trying to run
public class Runner {
public static void main(String[] args) {
Configuration configuration = new Configuration();
// либо в cfg прописать
// configuration.addAnnotatedClass(User.class);
// configuration.addAnnotatedClass(Ticket.class);
// configuration.addAnnotatedClass(Film.class);
configuration.configure();
try (SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession()) {
session.beginTransaction(); // начало
User user = User.builder()
.login("ivan#gmal.com")
.password("pass")
// Required type:javax.management.relation.Role
// Provided: cinema.entity.Role
.role(Role.USER) //got an error
.build();
session.save(user);
session.getTransaction().commit();//конец
}
}
}
i want to create and add to database user with enum
but cannot create instance
Required type:javax.management.relation.Role
Provided: cinema.entity.Role
how to fix it

#Formula Hibernate Annotation not evaluated

i just found out about the #Formula Annotation in Hibernate, but cannot get it to work.
I Tried using a hibernate Session to access the entites as well as a JPA Entitymanager with persistence.xml, in both cases my #Formula annotated field remains "null".
my Entity (copied from an Example):
#Entity(name = "Account")
public static class Account {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
private Double credit;
private Double rate;
#Formula(value = "credit * rate")
private Double interest;
//Getters and setters omitted for brevity
}
My Test-Setup (initializing a Session an an entitymanager for Test cases):
private SessionFactory sessionFactory;
private Session session = null;
EntityManager em;
#Before
public void before() {
EntityManagerFactory emf=Persistence.createEntityManagerFactory("test-pu");
em=emf.createEntityManager();
Configuration configuration = new Configuration();
configuration.addAnnotatedClass(TestEntity.class);
configuration.addAnnotatedClass(Account.class);
configuration.setProperty("hibernate.dialect",
"org.hibernate.dialect.PostgreSQL94Dialect");
configuration.setProperty("hibernate.connection.driver_class",
"org.postgresql.Driver");
configuration.setProperty("hibernate.connection.url",
"jdbc:postgresql://localhost:5432/Archiv");
configuration.setProperty("hibernate.hbm2ddl.auto",
"create");
configuration.setProperty("hibernate.connection.username",
"postgres");
configuration.setProperty("hibernate.connection.password",
"postgres");
sessionFactory = configuration.buildSessionFactory();
session = sessionFactory.openSession();
}
The persistence.xml for the entitymanager:
<persistence version="1.0" 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">
<persistence-unit name="test-pu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.test.ORMTest$Account</class>
<class>com.test.ORMTest$TestEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL94Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/Archiv"/>
<property name="hibernate.connection.username" value="postgres"/>
<property name="hibernate.connection.password" value="postgres"/>
<property name="hibernate.format_sql" value="true"/>
<property name="javax.persistence.validation.mode" value="NONE"/>
<property name="hibernate.service.allow_crawling" value="false"/>
<property name="hibernate.session.events.log" value="true"/>
</properties>
</persistence-unit>
</persistence>
And last but not least, the Test Code:
#Test public void emTest(){
em.getTransaction().begin();
Account account = new Account();
account.credit=100.0;
account.rate=0.1;
em.persist(account);
em.getTransaction().commit();
em.getTransaction().begin();
Account account1 = em.find(Account.class, 1l);
Double d = account1.getInterest();
System.out.println(d);
em.getTransaction().commit();
}
#Test
public void sessionTest() {
Transaction transaction = session.beginTransaction();
Account account = new Account();
account.credit=100.0;
account.rate=0.1;
session.save(account);
transaction.commit();
transaction = session.beginTransaction();
Account account1= session.get(Account.class, 1);
Double d = account1.getInterest();
System.out.println(d);
transaction.commit();
}
Both Cases print "null" for d.
According to the examples both cases should work. Anyone firm with Hibernate to tell me where i went wrong ?:/
Make sure that the object you expect to be set with Formula, is not getting loaded from the cache(where it having the same not set)

JPA Eclipselink Multitenant, table doesn't exist error

i'm trying to make a simple multitenant example to run, using Eclipselink 2.5.2, and MySQL.
When trying to persist an entity asigned to a tenant id, mysql server throws an error: "Table 'jpatest.tenant1_userdata' doesn't exist". (userdata being the entity, jpatest the database name, and tenant1 the tenant-id)
The table indeed doesn't exist, the database jpatest do exist. I was expecting eclipselink to autogenerate the tables each time i try to persist with a new tenant id.
So the question would be:
How can i force Eclipselink to create the tables?
If that is not possible; How can i create tables at runtime?
Here's the code:
Entity:
#Entity
#Table(name = "userdata")
#Multitenant(value = MultitenantType.TABLE_PER_TENANT)
#TenantTableDiscriminator(type = TenantTableDiscriminatorType.PREFIX, contextProperty = "tenant-id")
public class UserData implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private static final long serialVersionUID = 1L;
private String name;
.
.
.
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="MultiTeanantTest" transaction-type="RESOURCE_LOCAL">
<class>UserData</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpatest" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-database-schemas" value="true"/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Main class:
public class Main {
public static void main(String[] args) {
UserData ud = new UserData();
ud.setNombre("John);
Map properties = new HashMap<>();
properties.put("tenant-id", "tenant1");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MultiTeanantTest", properties );
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(ud);
em.getTransaction().commit();
}
}
Hope someone can give me a tip in what i'm doing wrong.
DDL generation will not be supported in a Multitenant Scenario by Eclipselink.
Refer to this link for more information, https://wiki.eclipse.org/EclipseLink/DesignDocs/Multi-Tenancy/TablePerTenant

Hibernate updating from different sessions

I am porting a java fat client from JDBC SQLite to Hibernate H2.
Until now I tried to separate all my database code in separate classes, like
TableTeam or TableMember, which have methods like .getAllTeams() or .updateTeam(Team t). These methods acted as a wrapper around their sql queries they executed.
Now with hibernate I tried to leave the interface as good as possible and just change the SQL queries to hibernate functions, which mostly works.
With one exception: updating elements.
team = new Team(-1, "Team Name", Collections.<Member>emptySet());
#Test
public void testUpdateTeam() throws Exception {
table.addTeam(team);
team.setName("New Name");
table.updateTeam(team);
Team f = table.getAllTeams().get(0);
Assert.assertEquals(team, f);
}
results in the following exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ch.tiim.sco.database.model.Team.members, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:156)
at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
at java.util.AbstractSet.equals(AbstractSet.java:92)
at org.hibernate.collection.internal.PersistentSet.equals(PersistentSet.java:441)
at ch.tiim.sco.database.model.Team.equals(Team.java:81)
at org.junit.Assert.isEquals(Assert.java:131)
at org.junit.Assert.equalsRegardingNull(Assert.java:127)
at org.junit.Assert.assertEquals(Assert.java:111)
at org.junit.Assert.assertEquals(Assert.java:144)
at ch.tiim.sco.database.TableMemberTest.testEditTeam(TableMemberTest.java:45)
The code for .updateTeam(Team t) is the following:
public void updateTeam(Team t) {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.update(t);
s.getTransaction().commit();
}
And the same for .addTeam(Team t) but s.save(t) instead of s.update(t)
And Team looks like this:
#Entity
#Table(name = "team")
public class Team implements Model {
#Id
#GeneratedValue
#Column(name = "team_id")
private int id;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "club_id")
private Club club;
#ManyToMany
#JoinTable(name = "team_members",
joinColumns = {#JoinColumn(name = "team_id")},
inverseJoinColumns = {#JoinColumn(name = "member_id")}
)
private java.util.Set<Member> members;
//I stripped the constructor and the setters/getters
}
Now how do I get rid of this error, without guaranteeing that every call to hibernate is from the same thread?
Edit Here is the hibernate configuration
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.h2.Driver</property>
<!--property name="connection.url">jdbc:h2:./test</property-->
<property name="connection.username">user</property>
<property name="connection.password">pass</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<!--property name="show_sql">true</property-->
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
</session-factory>
</hibernate-configuration>
For Junit testcases you need to bind an opened Session to the current Thread.
SessionFactory sf = null;
Session s = null;
SessionHolder holder = null;
#Override
protected void onSetUp() throws Exception {
System.out.println("On SetUP----");
sf = (SessionFactory) beanFactory.getBean("sessionFactory");
s = sf.openSession();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(s));
}
#Override
protected void onTearDown() throws Exception {
System.out.println("On onTearDown----");
// unbind and close the session.
holder = (SessionHolder)TransactionSynchronizationManager.getResource(sf);
s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sf);
SessionFactoryUtils.releaseSession(s, sf);
// teardown code here
}
If you want to no more care about LazyInitialisationException read this, its well explain what happens, and how to resolve the problem definitely
Can you post your hibernate.cfg? I suspect? you don't have a configured session context:
E.g
thread

Hibernate 4.3.6 and Glassfish 4.0 JPA 2.1 object is not an instance of declaring class

I'm using Hibernate 4.3.6 and Glassfish 4.0 for my ejb project.
My test Dao class :
#PersistenceContext
private EntityManager entityManager;
public void saveTest(){
Foo testFoo = new Foo();
testFoo.setSomething("test");
entityManager.persist(testFoo);
entityManager.flush();
}
and POJO class Foo.class:
#Entity
#Table(name = "FOO")
public class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String something;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "T_ID", unique = true, nullable = false, precision = 15, scale = 0)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "T_SOMETHING", length = 50)
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.adi = something;
}
}
persistence.xml :
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
version="2.1">
<persistence-unit name="TestAppUnit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/TestApp</jta-data-source>
<class>com.example.test.Foo</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
I can list table data, get data with query and i can remove data from table. But i can't persist or merge.
Exception is:
IllegalArgumentException occurred calling getter of com.example.test.Foo.id
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:192)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:346)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4746)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4465)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:243)
at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:511)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:100)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:671)
....
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:169)
Where am I doing wrong?
This project working on Glassfish 3.1 with persistence.xml version 1.0(jpa) and without this line :
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
Thanks in advance
I found it. Maybe others they encounter this problem. I wanted to share the solution.
The problem caused from Hibernate and "#PersistenceContext" annotation.
I change to Hibernate version to 4.3.5 and problem solved. Hibernate 4.3.6 and 4.3.7 has same problem. It's caused by different classloaders. Ejb Classloader and web app Classloader is different.

Categories

Resources