I'm using Gradle to manage my dependencies for Hibernate (I was previously using Maven), but I've encountered something strange. When I try to save a trivial instance of an annotated class to the database I wind up getting a MappingException saying said class is not mapped. This situation is somewhat unique because of the way I've been storing the instances. Assume that the situation is this: I have a properly annotated hibernate class that will be saved using the Session from an EntityManager using saveOrUpdate(). I have a persistance.xml, but no hibernate configuration files. I'm relying on the EntityManagers auto detection of mapped classes to feed it to the Session so it can be recognized as properly annotated. I'm using Hibernate 4.3.8. The code worked before the switch. All method calls take place in a transactional context and the transaction is committed and the session flushed.
Exception:
Caused by: org.hibernate.MappingException: Unknown entity: com.gmail.sarah.project.Rank
Gradle Dependencies:
compile "org.hibernate:hibernate-core:4.3.8.Final"
compile "org.hibernate:hibernate-entitymanager:4.3.8.Final"
compile "org.hibernate:hibernate-ehcache:4.3.8.Final"
compile "mysql:mysql-connector-java:5.1.35"
EDIT (A test case also has the same problem):
Main Class:
package com.gmail.physicistsarah.gradletestproject.core;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class Init {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("Test_Project");
EntityManager manager = factory.createEntityManager();
Session session = manager.unwrap(Session.class);
Transaction transaction = session.getTransaction();
transaction.begin();
session.saveOrUpdate(new Person("Carl", "Gauss"));
session.saveOrUpdate(new Person("Benoit", "Mandelbrot"));
transaction.commit();
factory.close();
}
#Entity
#Table(name = "Person")
public static class Person {
#Column(name = "First_Name", nullable = false)
private final String firstName;
#Column(name = "Last_Name", nullable = false)
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
}
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="Test_Project" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test_project_db?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
Build.gradle:
apply plugin: 'java'
apply plugin:'application'
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
// NetBeans will automatically add "run" and "debug" tasks relying on the
// "mainClass" property. You may however define the property prior executing
// tasks by passing a "-PmainClass=<QUALIFIED_CLASS_NAME>" argument.
//
// Note however, that you may define your own "run" and "debug" task if you
// prefer. In this case NetBeans will not add these tasks but you may rely on
// your own implementation.
mainClassName = "com.gmail.physicistsarah.gradletestproject.core.Init"
if (!hasProperty('mainClass')) {
ext.mainClass = 'com.gmail.physicistsarah.gradletestproject.core.Init'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
repositories {
mavenCentral()
// You may define additional repositories, or even remove "mavenCentral()".
// Read more about repositories here:
// http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:repositories
}
dependencies {
// TODO: Add dependencies here ...
// You can read more about how to add dependency here:
// http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
compile "org.hibernate:hibernate-core:4.3.8.Final"
compile "org.hibernate:hibernate-entitymanager:4.3.8.Final"
compile "org.hibernate:hibernate-ehcache:4.3.8.Final"
compile "mysql:mysql-connector-java:5.1.35"
testCompile group: 'junit', name: 'junit', version: '4.10'
}
Exception:
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Exception in thread "main" org.hibernate.MappingException: Unknown entity: com.gmail.physicistsarah.gradletestproject.core.Init$Person
at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1096)
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1443)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:242)
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)
at com.gmail.physicistsarah.gradletestproject.core.Init.main(Init.java:23)
The persistence.xml (and META-INF package) are in the resources/main folder.
You have many errors in your code:
Entities may not be nested classes
Entities must have a no-arg constructor
Entities fields may not be final
Entities must have an attribute annotated with #Id
Entities must be listed in the persistence.xml file:
<class>com.foo.bar.EntityClassName</class>
Related
I searched for similar topics. There are plenty of situations with this kind of problem but none was exactly mine, and none provided help. I am completly stuck at the moment, so I would really appreciate your help. Here's the situation:
I am trying to build a very simple app and, for now, just trying to connect everything together. My config files are the following:
pom.xml (containing a profile to facilitate the deployment):
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>hello</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<dependency>
<groupId>fish.payara.extras</groupId>
<artifactId>payara-embedded-all</artifactId>
<version>5.182</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>hello</finalName>
</build>
<profiles>
<profile>
<id>payara</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>fish.payara.maven.plugins</groupId>
<artifactId>payara-micro-maven-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<useUberJar>true</useUberJar>
<deployWar>true</deployWar>
<payaraVersion>5.182</payaraVersion>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
</project>
my web.xml (under webapp/WEB-INF):
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<data-source>
<name>java:global/hello</name>
<class-name>com.mysql.jdbc.Driver</class-name>
<url>jdbc:mysql://localhost:3306/connectiondatabase</url>
<user>root</user>
<password>mypass</password>
</data-source>
</web-app>
This database is running ok, and it was perfectly accessed from a general db client (dbeaver).
And finally, my persistence.xml (under resources/META-INF):
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
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="hello" transaction-type="JTA">
<jta-data-source>java:global/hello</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
I have a simple ping resource and JAXRS config class that came as default with the archtype I used to create the project (airhacks) and just one more simple entity, as follows:
package com.airhacks.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
#Entity
#Table(name = "players")
#NamedQuery(name = Player.FIND_PLAYER_BY_NAME, query = "select player from Player player where player.name =:" + Player.PLAYER_PARAMETER)
public class Player {
public static final String PLAYER_PARAMETER = "Player.name";
public static final String FIND_PLAYER_BY_NAME = "Player.findByName";
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
At this point, I can deploy the app with no errors (mvn clean package payara-micro:start), although when checking the database, no table is created (I thought persistence-unit would take care of that with both 'exclude-unlisted-classes' and 'drop-and-create', but apparently, something else is needed).
After that, for testing purposes, I am adding a queryService class, so I can actually use my datasource.
I am adding the following class:
package com.airhacks.services;
import com.airhacks.entities.Player;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
#Stateless
public class QueryService {
#PersistenceContext(unitName = "hello")
EntityManager entityManager;
public Player getPlayerByName(String name) {
try {
return entityManager.createNamedQuery(Player.FIND_PLAYER_BY_NAME, Player.class)
.setParameter(Player.PLAYER_PARAMETER, name)
.getSingleResult();
} catch (NoResultException | NonUniqueResultException e) {
return null;
}
}
}
As far as I understand, there's no need to detail anything else on the PersistenceContext annotation, as we only have one persistence unit (although I also added unitName="hello", with the same result). But once I try to deploy the app, I get the following errors:
[2021-02-13T13:50:07.023+0000] [] [SEVERE] [NCLS-CORE-00026]
[javax.enterprise.system.core] [tid: _ThreadID=1 _ThreadName=main]
[timeMillis: 1613224207023] [levelValue: 1000] [[ Exception during
lifecycle processing javax.persistence.PersistenceException: Exception
[EclipseLink-4002] (Eclipse Persistence Services - 2.7.1.qualifier):
org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: java.sql.SQLException: Error in allocating a connection.
Cause: The driver could not be loaded: com.mysql.jdbc.Driver Error
Code: 0
...
2.7.1.qualifier): org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: java.sql.SQLException: Error in allocating a connection.
Cause: The driver could not be loaded: com.mysql.jdbc.Driver Error
Code: 0
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:316) ...
... 41 more Caused by: java.sql.SQLException: Error in allocating a connection. Cause: The driver could not be loaded:
com.mysql.jdbc.Driver
... com.sun.appserv.connectors.internal.api.PoolingException:
So, basically, stating that the driver could not be loaded.
And this is where I can't do much. My external libs contain indeed mysql, so I don't understand where this problems comes from. I already tried with different db (SQLite, for example), but I get the very same problem, with different drivers, of course.
Would really appreciate your help and sorry for the long post.
Thank you!
This version of Mysql uses another driver class, change you web.xml from:
<class-name>com.mysql.jdbc.Driver</class-name>
to:
<class-name>com.mysql.cj.jdbc.MysqlConnectionPoolDataSource</class-name>
Reference: https://docs.payara.fish/community/docs/5.2020.5/documentation/payara-server/jdbc/mysql-connectorj-8-changes.html
I am trying to create a small H2 in-memory database while using hibernate. But the table is not dispplayed in the H2 UI. I'm not sure if I need to include anything else in the configuration.
Here is the code:
Below are dependencies added for hibernate and h2 DB.
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.1.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<version>1.4.200</version>
</dependency>
This is the configuration XML which has all the H2 DB details.
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 5.3//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-5.3.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</property>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="HiberDemo.Employee"/>
</session-factory>
</hibernate-configuration>
This creates the table along with the other columns.
Employee.java
package HiberDemo;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name= "emp500")
public class Employee {
#Id
private int id;
private String firstName,lastName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
This is to store some data into the table.
StoreData.java
package HiberDemo;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import com.sun.corba.se.pept.transport.Connection;
public class StoreData {
public static void main(String[] args) throws SQLException {
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
Metadata meta = new MetadataSources(ssr).getMetadataBuilder().build();
SessionFactory factory = meta.getSessionFactoryBuilder().build();
Session session = factory.openSession();
Transaction t = session.beginTransaction();
Employee e1=new Employee();
e1.setId(101);
e1.setFirstName("abc");
e1.setLastName("xyz");
session.save(e1);
t.commit();
System.out.println("successfully saved");
factory.close();
session.close();
// conn.close();
}
}
This is the H2 DB UI where the table I have created is not displayed.
Check logs if temporary database is created. If so url is consoled in logs:
2020-05-28 12:20:01.280 INFO 26579 --- [ restartedMain]
o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at
'/h2-console'. Database available at
'jdbc:h2:mem:b9994036-2f8e-4d00-8d7d-012a270661fa'
If you try connecting using jdbc:h2:mem:b9994036-2f8e-4d00-8d7d-012a270661fa, test connection works and tables are also shown:
You might need to downgrade your version and use the below
<dependency>
<groupId> com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
</dependency>
You must add the following two dependencies in your pom.xml
`
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
`
Then enable H2 console by adding the following line in application.properties file
spring.h2.console.enabled=true
After that run your application and open Rest endpoint "/h2-console"
Like: http://localhost:9090/h2-console/
Now copy your JDBC URL from the console
Like: Database available at 'jdbc:h2:mem:b61c56f6-93f3-4324-8b4a-4ead06f669d1'
Copy and paste in you H2 console, then click on 'Connect'
You can also configure manually everything by adding the following configuration in your application.properties file:
#---------------------------------DATABASE CONFIG-----------------------
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:person_db
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
#---------------------------------------------------------------
JPA dependency is missing. So, add below dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
This is the default login to the H2 database. Confirm if your details match
Change testdb to test in the screenshot above
you may need to add the following lines to the application.properties file.
spring.datasource.url= jdbc:h2:mem:test
I had the same problem. solved after couple of days :)
these 3 ways work same as each other.
downgrade your H2 dependency. if there isn't any version mentioned maven gets the latest so you might want to explicitly mention any version below 1.4.195
as below:
<dependency>
<groupId> com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
</dependency>
in your application properties write the full name of the database you want to connect to.
spring.datasource.url=jdbc:h2:mem:desiredName and in console use: jdbc:h2:mem:desiredName as name
by reading logs use the generated name. it differs time to time. H2 console available at '/h2'. Database available at 'jdbc:h2:mem:desiredName' this may have 16 letters after if no name is specified in application properties.
have fun.
I want to configure 2nd level hibernate cache at Spring Boot microservice.
And I don't want to use xml at all.
Next is my example.
UserEntity.java
#Entity
#Table(name = "users")
#Cacheable
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "users")
public class UserEntity {
#Id
private long id;
#Column
private String name;
public UserEntity(long id, String name) {
this.id = id;
this.name = name;
}
// ... geters&setters
}
CacheConfig.java
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableCaching
public class CacheConfig {
#Bean
public org.springframework.cache.CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheManager());
}
private net.sf.ehcache.CacheManager ehCacheManager() {
CacheConfiguration usersCacheConfiguration = new CacheConfiguration();
usersCacheConfiguration.setName("users");
usersCacheConfiguration.eternal(false);
usersCacheConfiguration.setMaxEntriesInCache(1000);
usersCacheConfiguration.setMaxEntriesLocalDisk(0);
usersCacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
config.addCache(usersCacheConfiguration);
return net.sf.ehcache.CacheManager.create(config);
}
}
App.java
#SpringBootApplication
public class App {
public static void main(String[] args) {
new SpringApplicationBuilder(App.class)
.sources(CacheConfig.class)
.run(args);
}
}
application.properties
spring:
datasource:
url: jdbc:postgresql://localhost:5432/test
username: postgres
password: postgres
type: com.zaxxer.hikari.HikariDataSource
driverClassName: org.postgresql.Driver
jpa.hibernate.ddl-auto: update
jpa.open-in-view: false
jpa.properties.javax.persistence.sharedCache.mode: ALL
jpa.properties.hibernate:
dialect: org.hibernate.dialect.PostgreSQL9Dialect
jdbc.batch_size: 100
temp.use_jdbc_metadata_defaults: false
order_inserts: true
cache:
region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
#region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
#region_prefix: ""
use_second_level_cache: true
cache.use_query_cache: true
provider_class: org.hibernate.cache.EhCacheProvider
build.gradle
group 'com.hibernate.cache'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.0.0.RELEASE'
compile group: 'org.springframework', name: 'spring-context-support', version: '5.0.4.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-ehcache', version: '5.2.14.Final'
compile group: 'org.postgresql', name: 'postgresql', version: '42.1.4'
}
When I run the program I see a couple of warnings indicating that entity cache configuration is not applied:
2018-03-04 23:29:48.723 WARN 8516 --- [ main] n.s.ehcache.config.ConfigurationFactory : No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/home/vitaly/.gradle/caches/modules-2/files-2.1/net.sf.ehcache/ehcache/2.10.3/cf74f9a4a049f181833b147a1d9aa62159c9d01d/ehcache-2.10.3.jar!/ehcache-failsafe.xml
2018-03-04 23:29:48.834 WARN 8516 --- [ main] o.h.c.e.AbstractEhcacheRegionFactory : HHH020003: Could not find a specific ehcache configuration for cache named [users]; using defaults.
Does anybody know what is wrong here?
The first warning:
2018-03-04 23:29:48.723 WARN 8516 --- [ main] n.s.ehcache.config.ConfigurationFactory : No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/home/vitaly/.gradle/caches/modules-2/files-2.1/net.sf.ehcache/ehcache/2.10.3/cf74f9a4a049f181833b147a1d9aa62159c9d01d/ehcache-2.10.3.jar!/ehcache-failsafe.xml
means that no ehcache.xml configuration was found so a default, ehcache-failsafe.xml, is used.
The second warning:
2018-03-04 23:29:48.834 WARN 8516 --- [ main] o.h.c.e.AbstractEhcacheRegionFactory : HHH020003: Could not find a specific ehcache configuration for cache named [users]; using defaults.
means that there was no configuration found for the "users" region in the cache. It is, of course, not defined in ehcache-failsafe.xml and it doesn't look like the settings in CacheConfig are being picked up - at least not by the CacheManager used by Hibernate.
It should be possible to solve both by adding an ehcache.xml to the classpath (in src/main/resources), e.g.:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<cache name="users"
maxEntriesLocalHeap="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
diskExpiryThreadIntervalSeconds="1"
copyOnRead="true"
copyOnWrite="true">
<copyStrategy class="net.sf.ehcache.store.compound.ReadWriteSerializationCopyStrategy" />
</cache>
</ehcache>
(see this ehcache.xml sample for more options)
And adding the following to application.yml:
spring:
cache:
ehcache:
config: classpath:ehcache.xml
A year late but the answer to your question might require you to implement your own RegionFactory class (by extending SingletonEhCacheRegionFactory) And then set your newly created class as the factory that hibernate should use: spring.jpa.properties.hibernate.cache.region.factory_class=com.my.class
https://stackoverflow.com/a/28594371/708854
I am setting up a new project using Tomcat, Weld (for CDI) and DeltaSpike (Data, JPA and JSF modules)
I have reached the point now where I am trying to create a JPA repository (backed by Hibernate) by following the directions in the DeltaSpike documentation (http://deltaspike.apache.org/documentation/data.html).
I am struggling to hook up the persistence unit in the way the documentation describes as my EntityManagerFactory object is always null
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
public class EntityManagerProducer {
#PersistenceUnit(unitName = "srdPersistenceUnit")
private EntityManagerFactory emf;
#Produces // you can also make this #RequestScoped
public EntityManager create() {
return emf.createEntityManager();
}
public void close(#Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
I have created a persistence.xml file which is in the /META-INF/ directory of the jar file that contains my service/data layer
<persistence version="2.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_2_0.xsd">
<persistence-unit name="srdPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/srdDCP</non-jta-data-source>
<properties>
</properties>
</persistence-unit>
</persistence>
I was previously using Spring to handle dependency injection and the JPA stuff which worked fine so I know my data source is set up correctly as a Tomcat JNDI resource.
Now however I see this exception (suggesting that the EntityManagerFactory is not being injected)
Caused by: java.lang.NullPointerException
at testproj.data.entity.EntityManagerProducer.create(EntityManagerProducer.java:18)
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.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:88)
at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:78)
at org.jboss.weld.injection.producer.ProducerMethodProducer.produce(ProducerMethodProducer.java:95)
at org.jboss.weld.injection.producer.AbstractMemberProducer.produce(AbstractMemberProducer.java:167)
at org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:183)
at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:69)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:101)
at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50)
at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:761)
at org.jboss.weld.bean.builtin.InstanceImpl.getBeanInstance(InstanceImpl.java:179)
at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:99)
at org.apache.deltaspike.data.impl.handler.EntityManagerLookup.lookupFor(EntityManagerLookup.java:58)
at org.apache.deltaspike.data.impl.handler.QueryHandler.createContext(QueryHandler.java:104)
at org.apache.deltaspike.data.impl.handler.QueryHandler.invoke(QueryHandler.java:77)
I suspect I have missed something in the setting up of the persistence unit.
What more do I need to do to create a valid persistence unit backed by hibernate jpa linked to my datasource?
Inside a controller my code was not persisting when I called .persist. I've also included my AppConfig for reference as well as my gradle dependencies. This is all on Tomcat7.
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_2_0.xsd"
version="2.0">
<persistence-unit name="main">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/dirtylibs"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Gradle
testCompile group: 'junit', name: 'junit', version: '4.11'
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
compile group: 'org.springframework', name: 'spring-webmvc', version: '3.2.5.RELEASE'
compile group: 'org.springframework', name: 'spring-orm', version: '3.2.5.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '4.3.0.Final'
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.0.Final'
runtime group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.3.0'
runtime group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.3.0'
runtime group: 'mysql', name:'mysql-connector-java', version: '5.1.26'
AppConfig
#Configuration
#EnableWebMvc
#ComponentScan(basePackageClasses = AppConfig.class)
#EnableTransactionManagement
public class AppConfig {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class.forName("com.mysql.jdbc.Driver").newInstance(); //This is some wierdness I needed to do because the mysql driver wasn't being picked up correctly
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
return localContainerEntityManagerFactoryBean;
}
}
My Controller
#Controller
public class SampleController {
#PersistenceContext
EntityManager entityManager;
#RequestMapping("home/test/{id}")
#ResponseBody
public List<Integer> getMessagesTest(#PathVariable Integer id) {
Phrase phrase = new Phrase();
entityManager.persist(phrase);
return Arrays.asList(phrase.getId());
}
}
According to
EntityManager persist() method does not insert record to database => SEVERE: javax.persistence.TransactionRequiredException
To persist data to a database using an entity manager I need to have it wrapped up in a transaction, which will call .flush() for me at the end of the transaction. Which means I need to add #Transaction to my controller, which I did. Now it looks like this.
#RequestMapping("home/test/{id}")
#ResponseBody
#Transactional
public List<Integer> getMessagesTest(#PathVariable Integer id) {
Phrase phrase = new Phrase();
entityManager.persist(phrase);
return Arrays.asList(phrase.getId());
}
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/orm/hibernate4/HibernateTransactionManager.html
Once I do that, I get the following exception.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined
Okay, no problem. It looks like the Hibernate 4 HibernateTransactionManager will do the job. Once I started to configure the HibernateTransactionManager in my AppConfig I realized I also needed a SessionFactory.
I very confused by all the options for creating a SessionFactory, and how it relates to my persistence.xml
My main question is how should I construct my session factory given my current setup?
Looking at the Spring docs it looks like I have to repeat all the information from my persistence.xml which seems really wrong to me. http://docs.spring.io/spring/docs/3.0.x/reference/orm.html#orm-hibernate
Any help would be much appreciated, including critique of the current setup. I really want to stick with the Java config, and avoid as much XML as possible. I'd even like to move away from the persistence-config.xml as described here, but I wanted to wait until it was working before trying that.
http://spring.io/blog/2011/06/10/spring-3-1-m2-configuration-enhancements/
Bozho's post over at Best Way to Inject Hibernate Session by Spring 3 gave me the information I needed to get it all tied together. I still haven't figured out if I need the persistence.xml, but now I'm recording entities to the database.
My new AppConfig now looks like this
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class.forName("com.mysql.jdbc.Driver").newInstance();
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
hibernateJpaVendorAdapter.setShowSql(true);
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(hibernateJpaVendorAdapter);
return localContainerEntityManagerFactoryBean;
}
#Bean
BasicDataSource basicDataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/dirtylibs");
basicDataSource.setUsername("root");
basicDataSource.setPassword("password");
return basicDataSource;
}
#Bean
JpaTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(localContainerEntityManagerFactoryBean.getObject());
return jpaTransactionManager;
}
I had to pull in another dependency for the BasicDataSource which came from Apache. Here are the Gradle coordinates.
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'