I'm using MySQL db to persist my entities in this project. I don't get any error messages from hibernate, but when I check in the database it's empty and no tables are created.
persistence.xml (edit: datasource added and transaction-type changed to JTA)
<?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="punit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/MySqlDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
At server start:
23:42:35,136 INFO [stdout] (ServerService Thread Pool -- 59) Hibernate: drop table if exists book
23:42:35,136 INFO [stdout] (ServerService Thread Pool -- 59) Hibernate: drop table if exists hibernate_sequence
23:42:35,136 INFO [stdout] (ServerService Thread Pool -- 59) Hibernate: create table book (id bigint not null, description varchar(255), illustrations bit, nbOfPage integer, price float, title varchar(255), primary key (id))
23:42:35,137 INFO [stdout] (ServerService Thread Pool -- 59) Hibernate: create table hibernate_sequence (next_val bigint)
23:42:35,137 INFO [stdout] (ServerService Thread Pool -- 59) Hibernate: insert into hibernate_sequence values ( 1 )
At runtime after persist:
23:42:56,796 INFO [stdout] (default task-4) Hibernate: update
hibernate_sequence set next_val= ? where next_val=?
23:42:56,807 INFO [stdout] (default task-4) Book "Java book" persisted! // I print this
23:42:56,814 INFO [stdout] (default task-4) Hibernate: insert into book
(description, illustrations, nbOfPage, price, title, id) values (?, ?, ?, ?, ?, ?)
pom.xml
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<scope>provided</scope>
</dependency>
I also ran query on entity manager after persist and it returns me a list of all persisted books, but none of them are in the database.
Code as requested
Book entity:
#Entity
#NamedQuery(name = "Book.findAll", query = "SELECT b FROM Book b")
public class Book implements Serializable {
#Id #GeneratedValue
private Long id;
private String title;
private Float price;
private String description;
private Integer nbOfPage;
private Boolean illustrations;
public Book() {
}
// getters, setters...
}
I persist entity in EJB like this:
#Named
#Stateless
public class BookEJB {
#PersistenceContext(unitName = "punit")
EntityManager em;
public Book createNewBook(Book book) {
em.persist(book);
System.out.println("Book \"" + book.getTitle() + "\" persisted!");
return book;
}
}
Update
I fixed persistence.xml, defined datasource in standalone.xml and put jdbc driver jar in server's directory following this tutorial.
But I get this exception:
23:12:11,374 INFO [org.jboss.as.jpa] (MSC service thread 1-3) WFLYJPA0002: Read persistence.xml for punit
23:12:11,625 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("add") failed - address: ([
("subsystem" => "datasources"),
("data-source" => "MySqlDS")
]) - failure description: {"WFLYCTL0180: Services with missing/unavailable dependencies" => [
"org.wildfly.data-source.MySqlDS is missing [jboss.jdbc-driver.mysql]",
"jboss.driver-demander.java:jboss/datasources/MySqlDS is missing [jboss.jdbc-driver.mysql]"
]}
PROBLEM SOLVED
In persistence.xml replaced <jta-data-source>jdbc/MySqlDS</jta-data-source> with <jta-data-source>java:jboss/datasources/MySqlDS</jta-data-source> which was the correct value of jndi-name attribute of my datasource definition inside standalone.xml file.
Also I've incorrectly put module.xml and jdbc connector jar inside modules\system\layers\base\com\mysql\driver\main but instead it needs to go to
modules\system\layers\base\com\mysql\main.
Seems i've been following some other tutorial alongside with the one in my post. ^^
Lets see extracts from the JPA 2.1 specification:
8.2.1.2 transaction-type
The transaction-type attribute is used to specify whether the entity managers provided by the entity manager factory for the persistence unit must be JTA entity managers or resource-local entity managers. The value of this element is JTA or RESOURCE_LOCAL. A transaction-type of JTA assumes that a JTA data source will be provided—either as specified by the jta-data-source element or provided by the container. In general, in Java EE environments, a transaction-type of RESOURCE_LOCAL assumes that a non-JTA datasource will be provided. In a Java EE environment, if this element is not specified, the default is JTA. In a Java SE environment, if this element is not specified, the default is RESOURCE_LOCAL.
You haven't specified the transaction-type attribute in the persistence-unit element. So, according to the spec (see the highlighted part above) you have the default which is JTA.
8.2.1.5 jta-data-source, non-jta-data-source
In Java EE environments, the jta-data-source and non-jta-data-source elements are used to specify the JNDI name of the JTA and/or non-JTA data source to be used by the persistence provider. If neither is specified, the deployer must specify a JTA data source at deployment or the default JTA data source must be provided by the container, and a JTA EntityManagerFactory will be created to
correspond to it.
You haven't also specified jta-data-source element in your persistence.xml as well, and I assume you haven't specified a JTA datasource during deployment. That means the default datasource will be provided by the container (see the highlighted text in the spec).
And this datasource is not pointing to your MySQL database. The default in Wildfly, unless you reconfigured it, is H2 database. So your program might be creating and populating tables in the default database. So you need to configure a datasource in Wildfly first and specify it in the persistence.xml.
That might be the reason for:
I also ran query on entity manager after persist and it returns me a list of all persisted books, but none of them are in the database.
It seems like you insert in one db, but check another db. Could you show datasource config?
P.S. It should be comment, but not enough rating(
Related
We have a custom keyloak user storage provide to use our proprietary user database for authentication.
This works perfectly fine with the WildFly based Keycloak. Since Keycloak will drop WildFly support in june 2022 according to their release notes, I am currently trying to get it running in the new, Quarkus based Keycloak distribution.
First I had to remove all dependencies provided by Quarkus since those lead to class loader issues. But now I am stuck with this error when I try to start Keycloak with the command ./kc.sh start-dev --log-level=ERROR:
Updating the configuration and installing your custom providers, if any. Please wait.
ERROR: Unexpected error when starting the server in (development) mode
ERROR: Failed to start quarkus
ERROR: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
ERROR: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.
And 'hibernate.dialect' is set in persistence.xml and configuring a persistance unit in persistence.xml should be supported according to quarkus documentation :
<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="example-pu" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.example.keycloak.provider.db.entity.Benutzer</class>
<class>com.example.keycloak.provider.db.entity.BenutzerWithSource</class>
<class>com.example.keycloak.provider.db.entity.Rolle</class>
<class>com.example.keycloak.provider.db.entity.Parameter</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
</properties>
</persistence-unit>
</persistence>
Configuring the dialect in an application.properties (according to https://quarkus.io/guides/hibernate-orm#multiple-persistence-units) file in the delivery didn't change the behavior as well:
quarkus.hibernate-orm."example-pu".hibernate-dialect=org.hibernate.dialect.OracleDialect
What am I missing?
Additional Persistence Units are not supported in Keycloak 17.0.0 with Quarkus.
This should be fixed in Keycloak 18.0.0: https://github.com/keycloak/keycloak/pull/10581.
I'm trying to deploy an EAR application (includes ejb and war modules). The problem is it cannot create indexes of a foreign key in associative entity (WorkerHasRole). Every entity with relationships was created automatically in IntelliJ. I am running it on Wildfly 25.0.0. I can't figure it out even with help of the internet...
Database diagram
database screenshot
Error that occures:
03:39:20,912 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 95) MSC000001: Failed to start service jboss.persistenceunit."officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS": org.jboss.msc.service.StartException in service jboss.persistenceunit."officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS": org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
at org.jboss.as.jpa#25.0.0.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:198)
at org.jboss.as.jpa#25.0.0.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:128)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at org.wildfly.security.elytron-base#1.17.1.Final//org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:664)
at org.jboss.as.jpa#25.0.0.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:213)
at org.jboss.threads#2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads#2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
at org.jboss.threads#2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads#2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.base/java.lang.Thread.run(Thread.java:833)
at org.jboss.threads#2.4.0.Final//org.jboss.threads.JBossThread.run(JBossThread.java:513)
Caused by: org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
at org.hibernate#5.3.23.Final//org.hibernate.boot.internal.InFlightMetadataCollectorImpl.buildUniqueKeyFromColumnNames(InFlightMetadataCollectorImpl.java:2137)
at org.hibernate#5.3.23.Final//org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processJPAIndexHolders(InFlightMetadataCollectorImpl.java:2149)
at org.hibernate#5.3.23.Final//org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1671)
at org.hibernate#5.3.23.Final//org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:287)
at org.hibernate#5.3.23.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1215)
at org.hibernate#5.3.23.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1246)
at org.hibernate.jipijapa-hibernate5-3#25.0.0.Final//org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
at org.jboss.as.jpa#25.0.0.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:170)
... 10 more
03:39:20,981 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 95) WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service 'officeApplication_ear_exploded/officeApplication.war#OfficeApplicationPU'
03:39:20,981 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 95) HHH000400: Using dialect: org.hibernate.dialect.MySQL55Dialect
03:39:20,983 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl] (ServerService Thread Pool -- 95) Envers integration enabled? : true
03:39:20,989 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "officeApplication_ear_exploded")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS\"" => "org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
Caused by: org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"}}
03:39:20,990 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "officeApplication_ear_exploded")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS\"" => "org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
Caused by: org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"}}
03:39:20,990 ERROR [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0021: Deploy of deployment "officeApplication_ear_exploded.ear" was rolled back with the following failure message:
{"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS\"" => "org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
Caused by: org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"}}
03:39:20,990 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 95) WFLYJPA0011: Stopping Persistence Unit (phase 1 of 2) Service 'officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS'
03:39:20,991 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 25) WFLYJPA0011: Stopping Persistence Unit (phase 2 of 2) Service 'officeApplication_ear_exploded/officeApplication.war#OfficeApplicationPU'
03:39:20,991 INFO [org.hibernate.orm.beans] (ServerService Thread Pool -- 25) HHH10005004: Stopping BeanContainer : org.hibernate.resource.beans.container.internal.CdiBeanContainerExtendedAccessImpl#27593d9a
03:39:20,991 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 25) WFLYJPA0011: Stopping Persistence Unit (phase 1 of 2) Service 'officeApplication_ear_exploded/officeApplication.war#OfficeApplicationPU'
03:39:20,993 INFO [org.jboss.as.server.deployment] (MSC service thread 1-2) WFLYSRV0208: Stopped subdeployment (runtime-name: officeApplication.jar) in 2ms
03:39:21,006 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) WFLYSRV0208: Stopped subdeployment (runtime-name: officeApplication.war) in 16ms
03:39:21,006 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) WFLYSRV0028: Stopped deployment officeApplication_ear_exploded (runtime-name: officeApplication_ear_exploded.ear) in 16ms
[2021-11-13 03:39:21,025] Artifact officeApplication:ear exploded: Error during artifact deployment. See server log for details.
[2021-11-13 03:39:21,025] Artifact officeApplication:ear exploded: java.lang.Exception: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"officeApplication_ear_exploded/officeApplication.jar#OfficeApplicationDS\"" => "org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
Caused by: org.hibernate.AnnotationException: Unable to create index (worker_idworker) on table worker_has_role: database column 'worker_idworker' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"}}
The class that makes error (I will also paste Worker Class just in case)
package ejbmodule.entities;
import javax.persistence.*;
#Table(name = "worker_has_role", indexes = {
#Index(name = "fk_worker_has_role_role1_idx", columnList = "role_idrole"),
#Index(name = "fk_worker_has_role_worker1_idx", columnList = "worker_idworker")
})
#Entity
public class WorkerHasRole {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idworker_has_role", nullable = false)
private Integer id;
#ManyToOne(optional = false)
#JoinColumn(name = "role_idrole", nullable = false)
private Role roleIdrole;
#ManyToOne(optional = false)
private Worker workerIdworker;
public Worker getWorkerIdworker() {
return workerIdworker;
}
public void setWorkerIdworker(Worker workerIdworker) {
this.workerIdworker = workerIdworker;
}
public Role getRoleIdrole() {
return roleIdrole;
}
public void setRoleIdrole(Role roleIdrole) {
this.roleIdrole = roleIdrole;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<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_2.xsd"
version="2.2">
<persistence-unit name="OfficeApplicationDS" transaction-type="JTA">
<class>ejbmodule.entities.Department</class>
<class>ejbmodule.entities.Position</class>
<class>ejbmodule.entities.WorkerId</class>
<class>ejbmodule.entities.Worker</class>
<class>ejbmodule.entities.Role</class>
<class>ejbmodule.entities.WorkerHasRole</class>
<jta-data-source>java:jboss/datasources/OfficeApplicationDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
pom.xml of ejb
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.example</groupId>
<artifactId>officeApplication</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>ejbmodule</groupId>
<artifactId>officeApplication_EJB</artifactId>
<version>1.0-SNAPSHOT</version>
<name>officeApplication_EJB</name>
<packaging>ejb</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<junit.version>5.7.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>javax.ejb-api</artifactId>
<version>3.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.5.3.Final</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
</plugins>
</build>
</project>
Worker class just in case
package ejbmodule.entities;
import javax.persistence.*;
#Table(name = "workers", indexes = {
#Index(name = "fk_worker_department1_idx", columnList = "department_iddepartment"),
#Index(name = "fk_worker_position1_idx", columnList = "position_idposition")
})
#Entity
public class Worker {
#EmbeddedId
private WorkerId id;
#Column(name = "name_worker", nullable = false, length = 45)
private String nameWorker;
#Column(name = "surname_worker", nullable = false, length = 45)
private String surnameWorker;
#Column(name = "phone_worker", nullable = false, length = 9)
private String phoneWorker;
#Column(name = "email_worker", nullable = false, length = 45)
private String emailWorker;
..... list of many repetetive columns .....
public WorkerId getId() {
return id;
}
public void setId(WorkerId id) {
this.id = id;
}
}
hibernate.cfg.xml placed in project_EJB directory: main->resources->hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/officedb</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<!-- DB schema will be updated if needed -->
<property name="hibernate.hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>
I'm running an Java EE application on Wildfly 15.0.1. I'm trying to use JPA without creating datasource on wildfly, because I want all the dependencies to be packed in application source code. I am using Maven to build the WAR.
I am using PostgreSQL and it's up and running on http://localhost:5432 I create db called testing for this project.
So, I added this dependency to my pom.xml:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
</dependency>
My persistence.xml is in src/main/resources/META-INF/persistence.xml:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.2"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="pu1">
<!-- classes -->
<class>myapp.model.Address</class>
<class>myapp.model.Transaction</class>
<properties>
<!-- database connection -->
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/testing" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="postgres" />
<!-- hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
I have #Entity annotation on both my Address and Transaction classes. But, nothing happens. Here's the log snippet:
22:58:05,759 INFO [org.hibernate.jpa.internal.util.LogHelper] (ServerService Thread Pool -- 103) HHH000204: Processing PersistenceUnitInfo [
name: pu1
...]
22:58:05,760 INFO [org.jboss.weld.deployer] (MSC service thread 1-5) WFLYWELD0003: Processing weld deployment myapp.backend-1.0.war
22:58:05,791 WARN [org.jboss.as.jaxrs] (MSC service thread 1-3) WFLYRS0018: Explicit usage of Jackson annotation in a JAX-RS deployment; the system will disable JSON-B processing for the current deployment. Consider setting the 'resteasy.preferJacksonOverJsonB' property to 'false' to restore JSON-B.
22:58:05,796 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-3) WFLYJCA0005: Deploying non-JDBC-compliant driver class org.postgresql.Driver (version 42.2)
22:58:05,810 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-8) WFLYJCA0018: Started Driver service with driver-name = myapp.backend-1.0.war_org.postgresql.Driver_42_2
22:58:05,816 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 103) WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service 'myapp.backend-1.0.war#pu1'
22:58:05,817 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 103) HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL94Dialect
22:58:05,820 INFO [org.hibernate.type.BasicTypeRegistry] (ServerService Thread Pool -- 103) HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType#6543510a
22:58:05,822 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl] (ServerService Thread Pool -- 103) Envers integration enabled? : true
22:58:05,858 INFO [org.hibernate.tool.schema.internal.SchemaCreatorImpl] (ServerService Thread Pool -- 103) HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl#4cc01a34'
22:58:05,858 INFO [org.hibernate.hql.internal.QueryTranslatorFactoryInitiator] (ServerService Thread Pool -- 103) HHH000397: Using ASTQueryTranslatorFactory
JPA specification:
8.2.1.2 transaction-type
The transaction-type attribute is used to specify whether the entity
managers provided by the entity manager factory for the persistence
unit must be JTA entity managers or resource-local entity managers.
The value of this element is JTA or RESOURCE_LOCAL. A transaction-type
of JTA assumes that a JTA data source will be provided—either as
specified by the jta-data-source element or provided by the container.
In general, in Java EE environments, a transaction-type of
RESOURCE_LOCAL assumes that a non-JTA datasource will be provided. In
a Java EE environment, if this element is not specified, the default
is JTA. In a Java SE environment, if this element is not specified,
the default is RESOURCE_LOCAL.
JTA is default transaction type in EE application server. To use it you need a datasource configured in WildFly. Then add it to persistence.xml:
<persistence-unit name="pu1" transaction-type="JTA">
<!-- classes -->
<class>myapp.model.Address</class>
<class>myapp.model.Transaction</class>
<properties>
<jta-data-source>jdbc/jndi_name_of_datasource</jta-data-source>
<!-- hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
I have a Spring Boot application
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
and hibernate is set to access the database in the application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/banquets-booking?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# this not helps as puts in quotes table field name only
#spring.jpa.properties.hibernate.globally_quoted_identifiers=true
#update validate create create-delete
spring.jpa.hibernate.ddl-auto=update
Now I have added a new field to the entity, but the update fails:
2018-09-03 13:05:34.893 TRACE 20867 --- [ restartedMain] org.hibernate.type.TypeFactory : Scoping types to session factory org.hibernate.internal.SessionFactoryImpl#56922754
Hibernate:
alter table banquets-booking.sub_event
add column outlet_id bigint
2018-09-03 13:05:35.841 WARN 20867 --- [ restartedMain] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
This looks like a bug, because Hibernate was able to generate the schema initially, but fails on the update.
How can I resolve this issue, without renaming the database?
This issue is not because of the minus sign.
You should try adding a dialects like one of the below lines.The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
OR
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQLMyISAMDialect
OR
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLInnoDBDialect
to see which one works for you.
Environment:
Java/Spring application that uses JPA/Hibernate for persistence and connects to a Teradata datasource configured in the app container (Tomcat) which is accessed through JNDI.
Versions that I am using:
java: 6
spring: 3.2.4.RELEASE
hibernate.core: 4.2.4.Final
hibernate.entitymanager: 4.2.4.Final
hibernate.validator: 5.0.1.Final
springdata: 1.3.4.RELEASE
javax.validation: 1.1.0.Final
Problem:
There are two Teradata databases in the same server that have a same named table but with different columns:
DatDe001.SFITEM
Columns: [iipcst, iidesc, iivend, updated_at, iisku#, created_at, item_expdt, item_effdt]
DEV_DIG_UMT.SFITEM
Columns: [iipcst, iidesc, iivend, row_updt_tms, iisku#, row_insrt_tms, item_expdt, item_effdt]
As you can see the columns that differ are updated_at -> row_updt_tms and created_at -> row_insrt_tms
I am using a JNDI datasource which is configured using this jdbc url:
jdbc:teradata://<server_ip>/DATABASE=DEV_DIG_UMT,DBS_PORT=1025,COP=OFF,CHARSET=UTF8,TMODE=ANSI
It is supposed that the jdbc connection will resolve the location of the table using the DATABASE value in that jdbc url. However Hibernate seems to be taking the wrong one: DatDe001.SFITEM when performing the initial schema validation, that is at the moment of context initialization when Spring tries to create the EntityManagerFactory bean:
2013-08-15 13:32:03,635 INFO localhost-startStop-1 org.hibernate.tool.hbm2ddl.TableMetadata - HHH000261: Table found: DatDe001.SFITEM
2013-08-15 13:32:03,635 INFO localhost-startStop-1 org.hibernate.tool.hbm2ddl.TableMetadata - HHH000037: Columns: [iipcst, iidesc, iivend, updated_at, iisku#, created_at, item_expdt, item_effdt]
So as my JPA entity (see the entity below in the post) does not have those columns, the hibernate validation throws an exception (see the summarized stack trace):
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [C:\APP\springsource\vfabric-tc-server-developer-2.9.2.RELEASE\base-instance\wtpwebapps\profile-items\WEB-INF\classes\META-INF\spring\applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [C:\APP\springsource\vfabric-tc-server-developer-2.9.2.RELEASE\base-instance\wtpwebapps\profile-items\WEB-INF\classes\META-INF\spring\applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1482)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
...
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:924)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:899)
...
Caused by: org.hibernate.HibernateException: Missing column: row_updt_tms in DatDe001.SFITEM
at org.hibernate.mapping.Table.validateColumns(Table.java:366)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1305)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:155)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:508)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1790)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914)
After I saw that, I was wondering if this behavior will persist when executing a query statement to the db through JPA/hibernate, or if it will point to the right table in that case.
Then just for investigation purposes I changed my JPA entity to have the same columns that DatDe001.SFITEM table:
#Entity
public class Sfitem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private SfitemPK id;
#Column(name="\"iidesc\"")
private String iidesc;
#Column(name="\"iipcst\"")
private BigDecimal iipcst;
#Column(name="\"iivend\"")
private BigDecimal iivend;
#Temporal
#Column(name="\"item_expdt\"")
private Date itemExpdt;
#Temporal
#Column(name="\"created_at\"")
private Date createdAt;
#Temporal
#Column(name="\"updated_at\"")
private Date updatedAt;
...
}
I started the application and it got loaded successfully. Instead of showing the exception now the log looked good:
...
2013-08-15 14:42:52,056 INFO localhost-startStop-1 org.hibernate.tool.hbm2ddl.TableMetadata - HHH000261: Table found: DatDe001.SFITEM
2013-08-15 14:42:52,056 INFO localhost-startStop-1 org.hibernate.tool.hbm2ddl.TableMetadata - HHH000037: Columns: [iipcst, iidesc, iivend, updated_at, iisku#, created_at, item_expdt, item_effdt]
2013-08-15 14:42:52,061 DEBUG localhost-startStop-1 org.hibernate.internal.SessionFactoryImpl - Checking 0 named HQL queries
2013-08-15 14:42:52,061 DEBUG localhost-startStop-1 org.hibernate.internal.SessionFactoryImpl - Checking 0 named SQL queries
2013-08-15 14:42:52,063 TRACE localhost-startStop-1 org.hibernate.service.internal.AbstractServiceRegistryImpl - Initializing service [role=org.hibernate.service.config.spi.ConfigurationService]
2013-08-15 14:42:52,113 TRACE localhost-startStop-1 org.hibernate.service.internal.AbstractServiceRegistryImpl - Initializing service [role=org.hibernate.stat.spi.StatisticsImplementor]
...
I tried to execute a query to the table and surprisingly found that this time Hibernate was pointing to the right database/schema: DEV_DIG_UMT, the query failed because now the entity had the columns for the other database: DatDe001, see the log:
2013-08-15 14:50:05,731 TRACE tomcat-http--4 org.hibernate.engine.query.spi.QueryPlanCache - Located HQL query plan in cache (SELECT o FROM Sfitem o WHERE o.id.iisku = :iisku AND o.id.itemEffdt <= :date AND coalesce(o.itemExpdt, cast('9999-12-31' as date)) >= :date)
2013-08-15 14:50:05,766 TRACE tomcat-http--4 org.hibernate.engine.query.spi.QueryPlanCache - Located HQL query plan in cache (SELECT o FROM Sfitem o WHERE o.id.iisku = :iisku AND o.id.itemEffdt <= :date AND coalesce(o.itemExpdt, cast('9999-12-31' as date)) >= :date)
2013-08-15 14:50:05,768 TRACE tomcat-http--4 org.hibernate.engine.query.spi.HQLQueryPlan - Find: SELECT o FROM Sfitem o WHERE o.id.iisku = :iisku AND o.id.itemEffdt <= :date AND coalesce(o.itemExpdt, cast('9999-12-31' as date)) >= :date
2013-08-15 14:50:05,772 TRACE tomcat-http--4 org.hibernate.engine.spi.QueryParameters - Named parameters: {iisku=387671, date=2013-08-08}
2013-08-15 14:50:05,810 DEBUG tomcat-http--4 org.hibernate.SQL - select sfitem0_."iisku#" as iisku1_0_, sfitem0_."item_effdt" as item_eff2_0_, sfitem0_."created_at" as created_3_0_, sfitem0_."iidesc" as iidesc4_0_, sfitem0_."iipcst" as iipcst5_0_, sfitem0_."iivend" as iivend6_0_, sfitem0_."item_expdt" as item_exp7_0_ from sfitem sfitem0_ where sfitem0_."iisku#"=? and sfitem0_."item_effdt"<=? and coalesce(sfitem0_."item_expdt", cast('9999-12-31' as DATE))>=?
2013-08-15 14:50:05,832 DEBUG tomcat-http--4 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not prepare statement [select sfitem0_."iisku#" as iisku1_0_, sfitem0_."item_effdt" as item_eff2_0_, sfitem0_."created_at" as created_3_0_, sfitem0_."iidesc" as iidesc4_0_, sfitem0_."iipcst" as iipcst5_0_, sfitem0_."iivend" as iivend6_0_, sfitem0_."item_expdt" as item_exp7_0_ from sfitem sfitem0_ where sfitem0_."iisku#"=? and sfitem0_."item_effdt"<=? and coalesce(sfitem0_."item_expdt", cast('9999-12-31' as DATE))>=?]
com.teradata.jdbc.jdbc_4.util.JDBCException: [Teradata Database] [TeraJDBC 14.00.00.21] [Error 3810] [SQLState 42S22] Column/Parameter 'DEV_DIG_UMT.sfitem0_.created_at' does not exist.
at com.teradata.jdbc.jdbc_4.util.ErrorFactory.makeDatabaseSQLException(ErrorFactory.java:307)
at com.teradata.jdbc.jdbc_4.statemachine.ReceiveInitSubState.action(ReceiveInitSubState.java:102)
at com.teradata.jdbc.jdbc_4.statemachine.StatementReceiveState.subStateMachine(StatementReceiveState.java:320)
at com.teradata.jdbc.jdbc_4.statemachine.StatementReceiveState.action(StatementReceiveState.java:201)
at com.teradata.jdbc.jdbc_4.statemachine.StatementController.runBody(StatementController.java:121)
at com.teradata.jdbc.jdbc_4.statemachine.StatementController.run(StatementController.java:112)
...
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:161)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:159)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1859)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1836)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1816)
at org.hibernate.loader.Loader.doQuery(Loader.java:900)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342)
at org.hibernate.loader.Loader.doList(Loader.java:2526)
at org.hibernate.loader.Loader.doList(Loader.java:2512)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2342)
at org.hibernate.loader.Loader.list(Loader.java:2337)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495)
This means that hibernate validation and the query executor routines are behaving differently
The entity with the correct fields:
#Entity
public class Sfitem implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private SfitemPK id;
#Column(name="\"iidesc\"")
private String iidesc;
#Column(name="\"iipcst\"")
private BigDecimal iipcst;
#Column(name="\"iivend\"")
private BigDecimal iivend;
#Column(name="\"item_expdt\"")
private Date itemExpdt;
#Column(name="\"row_insrt_tms\"")
private Timestamp rowInsrtTms;
#Column(name="\"row_updt_tms\"")
private Timestamp rowUpdtTms;
...
}
Persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.TeradataDialect"/>
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<!-- Uncomment the following two properties for JBoss only -->
<!-- property name="hibernate.validator.apply_to_ddl" value="false" /-->
<!-- property name="hibernate.validator.autoregister_listeners" value="false" /-->
</properties>
</persistence-unit>
</persistence>
Datasource and entity manager beans:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${datasource.jndiName}"/>
<property name="lookupOnStartup" value="true"/>
<property name="resourceRef" value="true" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
Is that a bug or a configuration issue? Has anyone faced this same issue?
I don't want to configure a default schema in the persistence unit nor in the entities, because the approach we are following is to keep the datasource configuration outside the application and in a single place by using the JNDI datasource defined in the container context. That way we don't need to worry when deploying to different environments (Dev, QA, Prod, etc)
You may need to fully qualify your table name in your SELECT queries that are being submitted to Teradata.
select sfitem0_."iisku#" as iisku1_0_, sfitem0_."item_effdt" as item_eff2_0_,
sfitem0_."created_at" as created_3_0_, sfitem0_."iidesc" as iidesc4_0_,
sfitem0_."iipcst" as iipcst5_0_, sfitem0_."iivend" as iivend6_0_,
sfitem0_."item_expdt" as item_exp7_0_
from DatDe001.SFITEM sfitem0_ /* Notice database name is included here */
where sfitem0_."iisku#"=?
and sfitem0_."item_effdt"<=?
and coalesce(sfitem0_."item_expdt", cast('9999-12-31' as DATE))>=?
Edit
You could also construct a string that you execute before each SELECT statement that specifies the schema/database you wish to use as the default database to be used to find objects that are not fully qualified in your SQL:
DATABASE=?
Then possibly use a parameter to provide that value like you are the values for your WHERE clause
Edit 2
You can only specify a single DATABASE parameter for a given connection string. If your requirement is to allow for different names for the database supporting the application front end you will need to parameterize the connection string for each database that the application will need to communicate with on the backend.