JPA Eclipselink Multitenant, table doesn't exist error - java

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

Related

I don't know why my very simple JPA project doesn't work

I have org.postgresql.util.PSQLException: ERROR: relation "roles" does not exist, and I don't know why.
Entity class
package com.example.SpringBootTest1.model;
import lombok.*;
import javax.persistence.*;
#ToString
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "roles")
public class Role
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter
#Getter
private int id;
#Setter
#Getter
#Column(name = "name")
private String name;
}
main()
public static void main(String[] args)
{
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("role_pu");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
Role role1 = new Role();
role1.setName("role111");
entityManager.persist(role1);
entityManager.getTransaction().commit();
entityManagerFactory.close();
entityManager.close();
}
resources/META-INF/persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="role_pu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.example.SpringBootTest1.model.Role</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/postgres"/>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="javax.persistence.jdbc.password" value="123"/>
<property name="dialect" value="org.hibernate.dialect.PostgreSQL94Dialect"/>
<property name="show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hdm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
In pom.xml I have
hibernate-core
postgresql
lombok
So why I have such error and why is that? I have read this question and it doesn't help me.
In modern Hibernate versions, the property hdm2ddl.auto should be hibernate.hbm2ddl.auto or javax.persistence.schema-generation.database.action.
https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl

querying mongodb hibernate ogm return always null

i want to query a mongodb here my code
Persistence.xml
<?xml version="1.0"?>
<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="primary" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
<property name="hibernate.ogm.datastore.provider" value="mongodb" />
<property name="hibernate.ogm.datastore.database" value="******" />
<property name="hibernate.ogm.datastore.host" value="******" />
<property name="hibernate.ogm.datastore.port" value="******" />
<property name="hibernate.ogm.datastore.username" value="******" />
<property name="hibernate.ogm.datastore.password" value="******" />
</properties>
</persistence-unit>
</persistence>
Flux.java
#Entity
#Table(catalog="f12", schema="public", name="enl_flux_f12_entry")
public class enl_flux_f12_entry{
#Id
public String id;
public String SYS_FluxName;
public byte[] SYS_ReadDateTime;
public String SYS_BaseNameZip;
public Long SYS_Status;
public String SYS_DateCreaERDF;
}
main
public static void main(String[] args) throws ClassNotFoundException{
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "primary" );
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
enl_flux_f12_entry f = entityManager.find(Flux.class, "*id*");
System.out.println(f.id);
entityManager.flush();
entityManager.close();
}
mongodb
{
"_id" : ObjectId("rzerzer"),
"SYS_FluxName" : "zerzerze.xml",
"SYS_ReadDateTime" : Timestamp(6300883749567463, 83),
"SYS_BaseNameZip" : "rferfer.zip",
"SYS_Status" : NumberLong(1),
"SYS_DateCreaERDF" : "2016-03-01T20:38:48Z"
}
The problem is that entityManager.find return always null. Is there any problem in my code?
I think it returns null because something odd in the mapping or in the JSON object and it cannot find the entity you are looking for.
The JSON object you want to get has _id: ObjectId("rzerzer"), this doesn't look right because an ObjectId in MongoDB should be:
The 12-byte ObjectId value consists of:
a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
Even if the object in the DB is right, it is mapped as a String, so Hibernate OGM does not expect an ObjectId.
The mapping of the id on the entity should be:
#Id
#Type(type = "objectid")
public String id;
or
#Id
public ObjectId id;
Another strange thing is the way you are using find:
enl_flux_f12_entry f = entityManager.find(Flux.class, "*id*");
the find method requires the exact id of the entity. If the mapping is right, this should work entityManager.find(Flux.class, "rzerzer");
If you are not sure about the id value in the db you can also use HQL:
List<Flux> entries = entityManager.createQuery( "from Flux" ).list();

#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)

How to prevent Hibernate cache?

I'm working on an web application using Hibernate 4, Spring 3. I'm struggling with an issue for days.
In the application I have an entity class named 'User':
#Entity
public class User {
#Id
private int uid;
#Column(unique = true)
private String username;
private String password;
private boolean confirmed;
//... getters and setters
}
This entity class is mapped from a table of db called 'user'.
There is another entity class named 'Confirmation':
#Entity
#NamedQueries({
#NamedQuery(name = "getAllConfirmations", query = "select c from Confirmation c")
})
public class Confirmation {
#Id
private String username;
private boolean confirmed;
//... getters and setters
}
This entity class is mapped from a view of db called 'confirmation'.
create view confirmation
as
select username,confirmed from user
I have a method in my service class to get list of all Confirmation object:
public List<Confirmation> getListOfConfirmations() {
Query query = entityManager.createNamedQuery("getAllConfirmations");
return query.getResultList();
}
Also, there's a method to confirm User objects- set confirmed field 'true':
public int confirmUser(int uid) {
User user = getUser(uid);
if (user != null) {
user.setConfirmed(true);
try {
entityManager.getTransaction().begin();
entityManager.merge(user);
entityManager.getTransaction().commit();
return 1;
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
When I call confirmUser() it works fine and User object and it's row in database would be changed, But when I call getListOfConfirmations() after changes no change would be viewed in the result list.
It seems, by default, hibernate caches query result of views.
Is there any way to prevent hibernate to prevent caches this result.
In addition, I've tried #Cacheable(false) for Confirmation class or set #QueryHint(name = "org.hibernate.cacheable", value = "false") for getAllConfirmations named query, these don't work.
Persistence config:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="MyPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>bob.jpacache.Confirmation</class>
<class>bob.jpacache.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/cachetest"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="root"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Thanks, in advance, for your help.
#Cacheable refers to the second-level cache and your problem seems to me that it is in the first level cache. I believe that the problem is in the life cycle of your EntityManager (at what time you create a new, at what time you close it), do a simple test: after the change of the User's objects, try call entityManager.clear () and then query your Confirmation object. NOTE: entityManager.clear () must be called on the same EntityManager that will be used to make the query.
Another detail, do not know what his real purpose, but the query has no filter. Thus, whether the User has to confirm or not, will always bring all records of User table.

org.apache.openjpa.persistence.ArgumentException while running the main class

I using using maven simple java project
Im getting the following exception while running the main class
346 INFO [main] openjpa.Runtime - OpenJPA dynamically loaded the class
enhancer. Any classes that were not enhanced at build time
will be enhanced when they are loaded by the JVM.
414 INFO [main] openjpa.Runtime - Starting OpenJPA 2.3.0
<openjpa-2.3.0-r422266:1540826 fatal user error>
org.apache.openjpa.persistence.ArgumentException: The persistence provider is
attempting to use properties in the persistence.xml file to resolve the data
source. A Java Database Connectivity (JDBC) driver or data source class name
must be specified in the openjpa.ConnectionDriverName or
javax.persistence.jdbc.driver property. The following properties are available
in the configuration: "org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl#442ce698".
at org.apache.openjpa.jdbc.schema.DataSourceFactory.newDataSource(DataSourceFactory.java:72)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.createConnectionFactory(JDBCConfigurationImpl.java:849)
at org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.getDBDictionaryInstance(JDBCConfigurationImpl.java:602)
at org.apache.openjpa.jdbc.meta.MappingRepository.endConfiguration(MappingRepository.java:1518)
at org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations.java:535)
at org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations.java:460)
at org.apache.openjpa.lib.conf.PluginValue.instantiate(PluginValue.java:121)
at org.apache.openjpa.conf.MetaDataRepositoryValue.instantiate(MetaDataRepositoryValue.java:68)
at org.apache.openjpa.lib.conf.ObjectValue.instantiate(ObjectValue.java:83)
at org.apache.openjpa.conf.OpenJPAConfigurationImpl.newMetaDataRepositoryInstance(OpenJPAConfigurationImpl.java:967)
at org.apache.openjpa.conf.OpenJPAConfigurationImpl.getMetaDataRepositoryInstance(OpenJPAConfigurationImpl.java:958)
at org.apache.openjpa.kernel.AbstractBrokerFactory.makeReadOnly(AbstractBrokerFactory.java:643)
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:203)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:155)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:226)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:153)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:59)
at org.msharma.JpaImpl.main(JpaImpl.java:15)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
My entity clas
#Entity(name ="customer")
public class Customer implements Serializable{
#Id
#Column(name ="cust_id", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private long custId;
#Column(name = "first_name",length = 50, nullable = false)
private String firstName;
#Column(name = "last_name",length = 50)
private String lastName;
// By default column name is same as attribute name
private String street;
private String appt;
private String city;
#Column(name = "zip_code",length = 50, nullable = false)
private String zipCode;
#Column(name = "cust_type",length = 50, nullable = false)
private String custType;
#Version
#Column(name = "last_updated_time")
private Date updatedTime;
public Customer(){}
// getters and setters
}
This is my persistence.xml
<?xml version="1.0"?>
<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="testjpa" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>org.somepack.Customer</class>
<properties>
<property name="openjpa.ConnectionURL"
value="jdbc:mysql://localhost:3306/test"/>
<property name="openjpa.ConnectionDriverName"
value="com.mysql.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="pass"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>
This is my mainClass
public static void main(String[] args) {
try {
EntityManagerFactory entityManagerFactory = Persistence
.createEntityManagerFactory("testjpa");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
Customer customer = new Customer();
//set the properties to the customer object
entityManager.persist(customer);
entityTransaction.commit();
entityManager.close();
entityManagerFactory.close();
}
catch (Exception e){
e.printStackTrace();
}
}
How do I resolve the problem .
I have openjpa, openjpa-persistence-jdbc, mysql-connector-java dependencies in my POM.xml
and my persistence.xml is under src/main/resources
As you said your persistence.xml is under src/main/resources so may be it is unable to read it
you must place it under src/main/resources/META-INF
One more thing add
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
to your persistence.xml.
If you add the openjpa.jdbc.SynchronizeMappings property as shown below OpenJPA will auto-create all your tables, all your primary keys and all foreign keys exactly to match your objects
Add <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> to your persistence.xml:
<?xml version="1.0"?>
<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="testjpa" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>org.somepack.Customer</class>
<properties>
<property name="openjpa.ConnectionURL"
value="jdbc:mysql://localhost:3306/test"/>
<property name="openjpa.ConnectionDriverName"
value="com.mysql.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="pass"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
</properties>
</persistence-unit>
</persistence>

Categories

Resources