Can't find persistence.xml - java

I try to use jpa with spring-orm and hibernate.
I have mysql db with TRADES table. I try to work with this table using jpa.
I try to test EntityManager creation using persistence.xml but I get an exception that "No Persistence provider for EntityManager named [persistence-unit-name from persistence.xml]"
As I watched in another such questions, it's mean for my situation that persistence.xml file is not found.
When I try to test this configuration I get an exception that persistence.xml wasn't find, as I think.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named trade-mysql-pu
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
at com.madhusudhan.jsd.jpa.EntityManagerTest.init(EntityManagerTest.java:16)
at com.madhusudhan.jsd.jpa.EntityManagerTest.main(EntityManagerTest.java:29)
I can't figure out why this is happening. Could you help me?
Thanks.
Table:
create table TRADES (ID int NOT NULL,
ACCOUNT VARCHAR(20) NOT NULL,
SECURITY VARCHAR(10) NOT NULL,
QUANTITY INT NOT NULL,
STATUS VARCHAR(10),
DIRECTION VARCHAR(10)
);
entity class for this table:
package com.madhusudhan.jsd.domain.jpa;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="trades")
public class Trade {
private int id;
private String direction;
private String account;
private String security;
private String status;
private int quantity;
#Column(nullable=false)
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
#Column
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
#Column
public String getSecurity() {
return security;
}
public void setSecurity(String security) {
this.security = security;
}
#Column
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Column
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
#Override
public String toString() {
return "Trade [id=" + id + ", direction=" + direction + ", account="
+ account + ", security=" + security + ", status=" + status
+ "]";
}
}
And persistence.xml in src/main/resources/META-INF
<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="trade-mysql-pu" transaction-type="RESOURCE_LOCAL">
<provider>org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter</provider>
<class>com.madhusudhan.jsd.domain.jpa.Trade</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="show_sql" value="true" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/JSDATA"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="prospring4"/>
<property name="hibernate.connection.password" value="prospring4"/>
<property name="hibernate.connection.pool_size" value="1"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
</properties>
</persistence-unit>
</persistence>
This is the test class:
package com.madhusudhan.jsd.jpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.madhusudhan.jsd.domain.jpa.Trade;
public class EntityManagerTest {
private EntityManagerFactory factory;
private EntityManager entityManager;
private void init() {
factory = Persistence.createEntityManagerFactory("trade-mysql-pu");
entityManager = factory.createEntityManager();
}
public void persistTrade(Trade t) {
entityManager.persist(t);
}
public static void main(String[] args) {
EntityManagerTest test = new EntityManagerTest();
test.init();
}
}
dependencies from build.gradle:
dependencies {
compile 'org.springframework:spring-context:4.1.6.RELEASE'
compile 'org.springframework:spring-jdbc:4.1.6.RELEASE'
compile 'org.springframework:spring-orm:4.1.6.RELEASE'
compile 'commons-dbcp:commons-dbcp:1.4'
compile 'mysql:mysql-connector-java:5.1.18'
compile 'org.hibernate:hibernate-core:3.6.0.Final'
compile 'org.hibernate:hibernate-entitymanager:3.6.0.Final'
compile 'junit:junit:4.7'
compile 'log4j:log4j:1.2.14'
}

Few things you can try:
Check that your src/main/resources folder is in your classpath. In Eclipse, it means right click on the project > Properties > Java Build Path and make sure that src/main/resources is specified under Source tab. If it is not there, click Add Folder to add resources folder.
If the above does not work, try to move your persistence.xml to src/main/java/META-INF folder.
Change to provider in persistence.xml to
org.hibernate.ejb.HibernatePersistence

Related

Java Hibernate attributeoverride annotation not working?

Hi I am currently learning Hibernate and I am stuck on a problem where I am trying to override the column name from address to home address and office address. I commented out all office-address code, but the column in database are still "CITY_NAME", "STREET_NAME" and etc.
Could someone please explain this, thanks.
Address.java
package org.zm.javabrain.dto;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class Address {
#Column(name="STREET_NAME")
private String stree;
#Column(name="CITY_NAME")
private String city;
#Column(name="STATE_NAME")
private String state;
#Column(name="ZIP_NAME")
private String zip;
public String getStree() {
return stree;
}
public void setStree(String stree) {
this.stree = stree;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
this is UserDetails.java
package org.zm.javabrain.dto;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
#Entity // change the name of the entity
#Table(name="USER_DETAILS") // change the name of the table
public class UserDetails implements Serializable {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
private String username;
private Date joinedDate;
private String description;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="street",column=#Column(name="HOME_STREET_NAME")),
#AttributeOverride(name="city",column=#Column(name="HOME_CITY_NAME")),
#AttributeOverride(name="state",column=#Column(name="HOME_STATE_NAME")),
#AttributeOverride(name="zip",column=#Column(name="HOME_ZIP_NAME"))})
private Address homeAddress;
// #Embedded
// #AttributeOverrides({
// #AttributeOverride(name="street",column=#Column(name="OFFICE_STREET_NAME")),
// #AttributeOverride(name="city",column=#Column(name="OFFICE_CITY_NAME")),
// #AttributeOverride(name="state",column=#Column(name="OFFICE_STATE_NAME")),
// #AttributeOverride(name="zip",column=#Column(name="OFFICE_ZIP_NAME"))})
// private Address officeAddress;
//
// public Address getOfficeAddress() {
// return officeAddress;
// }
// public void setOfficeAddress(Address officeAddress) {
// this.officeAddress = officeAddress;
// }
public Date getJoinedDate() {
return joinedDate;
}
public void setJoinedDate(Date joinedDate) {
this.joinedDate = joinedDate;
}
public Address getHomeAddress() {
return homeAddress;
}
public void setHomeAddress(Address homeAddress) {
this.homeAddress = homeAddress;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
This is driver class
package org.zm.hibernate;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.zm.javabrain.dto.Address;
import org.zm.javabrain.dto.UserDetails;
public class HibernateTest {
public static void main(String[] args) {
UserDetails user = new UserDetails();
Address addr = new Address();
addr.setCity("chicago");
addr.setState("IL");
addr.setStree("Michigen Ave");
addr.setZip("55414");
Address officeAddr = new Address();
officeAddr.setCity("minneapolis");
officeAddr.setState("Washington Ave");
officeAddr.setState("MN");
officeAddr.setZip("55455");
user.setUsername("11111");
user.setHomeAddress(addr);
// user.setOfficeAddress(officeAddr);
user.setJoinedDate(new Date());
user.setDescription("this is a description");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
}
I cannot tell you if Hibernate Session supports the AttributeOverride feature or not. The problem is, I guess, Hibernate is mixing two different technologies that are trying to solve the same problem, and that is confusing for new users trying to learn. Hibernate can be used as
Legacy (Native) ORM , and
JPA (Java Persistence API) implementation
As I can see from your posted code example that you are using JPA annotations. All annotations, classes and properties having the package structure of javax.persistence are JPA specific. So my advice is, either configure your persistence the Hibernate way or the JPA way, and don't mix.
If you want to map your entities the JPA way, do the following:
Put your configuration information in the file persistence.xml instead of in the hibernate.cfg.xml. The file should be under META-INF folder of your source directory. If you are using Maven put it under src/main/resources/META-INF directory. The file should look like:
<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="yourPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>org.zm.javabrain.dto.UserDetails</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="..." />
<property name="javax.persistence.jdbc.url" value="..." />
<property name="javax.persistence.jdbc.user" value="..." />
<property name="javax.persistence.jdbc.password" value="..." />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
replace the ... with correct database information.
In your test class (HibernateTest) do the following instead of SessionFactory / Session:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("yourPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit;
em.close();
emf.close();
You can also read:
Hibernate User Guide
Java Persistence API Tutorials
JPA 2.1 Specification
Hopefully, it helps.

JUnit error "Unknown entity type" when using entities from a jar-file

I'm struggling with an error in my Java project.
Running my code in a local project without any connection to GitHub, everything works fine. As soon as I run the Junit4 test of the same code in a project connected to GitHub, this error occurs:
Java.lang.IllegalArgumentException: An exception occured while creating a query in EntityManager:
Exception Description: Error compiling the query SELECT entity FROM DoSomething entity. Unknown entity type DoSomething.
I am using Eclipse, EclipseLink, PostgreSQL and JPA. The Database is on my localhost. Might there be any problems to find localhost while running the Git Project? I have a local repository for the GitProject so I can't imagine that this is really a problem.
This is the persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="myDatabase" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/myDatabase" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="secret" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
<shared-cache-mode>NONE</shared-cache-mode>
<property name="eclipselink.logging.level" value="off"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
</properties>
</persistence-unit>
*EDIT:
This is my entity class.
import javax.persistence.*;
#Entity
#NamedQueries({
#NamedQuery(name = "findByName", query = "SELECT r FROM DoSomething r WHERE r.name = :name"),
#NamedQuery(name = "findByPreis", query = "SELECT r FROM DoSomething r WHERE r.preis = :preis"),
})
public class DoSomething {
#Id
#GeneratedValue
private int id;
private String name;
private double preis;
public DoSomething() {
}
public DoSomething(String name, double preis) {
this.name = name;
this.preis = preis;
}
public DoSomething(String name){
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPreis() {
return preis;
}
public void setPreis(double preis) {
this.preis = preis;
}}
I exported the entity class into a jar-file. Then I opened a new project where the jar-file is referenced. In this project there is a class that persists the entity to the database. Due to a performance requirement I have to separate the entity and the persisting class into two projects.
This ist the persisting class:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import demo.persistence.jpa.JpaUtil;
public class DoSomethingDAO {
public void save(DoSomethingDAO entity) throws Exception {
EntityManager em = JpaUtil.createEntityManager();
try {
em.getTransaction().begin();
em.persist(entity);
em.getTransaction().commit();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
throw e;
} finally {
em.close();
}
}
public List<DoSomethingDAO> findByName(String name) throws Exception {
EntityManager em = Persistence.createEntityManagerFactory("myDatabase").createEntityManager();
List<DoSomethingDAO> bList = new ArrayList<DoSomethingDAO>();
try {
TypedQuery<DoSomethingDAO> tQuery = em.createNamedQuery("findByName", DoSomethingDAO.class);
tQuery.setParameter("name", name);
bList = tQuery.getResultList();
em.close();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
e.printStackTrace();
}
return bList;
}
}
Looks like your persistence.xml not on the classpath while running in tests. Tests scope has another classpath then main one. But I don't know how to set up this in eclipse.
I added
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>packagename.DoSomehting</class>
for all classes to the xml-File. Works fine now.

How can I change this configuration so I can work with Hibernate?

This is my project structure:
I have these following files:
context.xml
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="jdbc/sakila"
url="jdbc:mysql://localhost/sakila"
username="root"
password=""
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource"
maxActive="20" maxIdle="5" maxWait="10000"
/>
</Context>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="sakila" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/sakila</non-jta-data-source>
</persistence-unit>
</persistence>
And in a DAO class I can use:
EntityManagerFactory sakilaFactory = Persistence.createEntityManagerFactory("sakila");
EntityManager entityManager = sakilaFactory.createEntityManager();
which all works fine..
But I want to change my configuration to using .xml files and instead of EntityManager I want to use Session from Hibernate API.
I have looked at several tutorials on the web but I am only more confused. How should I use the .xml files for Hibernate configuration?
I am running the application on Tomcat and here is my dependencies from pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>provided</scope>
</dependency>
What I want to achieve is a proper Hibernate configuration, and using Session instead of EntityManager.
Edit #1: This is what my Actor class looks like:
package biz.tugay.model;
/* User: koray#tugay.biz Date: 06/08/15 Time: 09:17 */
import javax.persistence.*;
import java.sql.Timestamp;
#Entity
#Table(name = "actor")
public class Actor {
private Integer actor_id;
private String first_name;
private String last_name;
private Timestamp last_update;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getActor_id() {
return actor_id;
}
public void setActor_id(Integer id) {
this.actor_id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public Timestamp getLast_update() {
return last_update;
}
public void setLast_update(Timestamp last_update) {
this.last_update = last_update;
}
#Override
#Transient
public String toString() {
return "Actor{" +
"id=" + actor_id +
", first_name='" + first_name + '\'' +
", last_name='" + last_name + '\'' +
", last_update=" + last_update +
'}';
}
}
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:PORT/databasename</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">XXXX</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">create </property>
<property name="hbm2ddl.auto">validate</property>
<mapping class="com.packageClass"/>
<mapping class="com.package.OtherClass"/>
</session-factory>
you should have the hibernate.cfg.xml - configuration file for hibernate; i gave you a template above.It should be placed in the src of your java resources. Now you can use annotations for persistance. And you should also add #Column annotation on every attribute in you actor class to map every attribute on an attribute from your table.Here is an example class
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="useri")
public class User implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id_user;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#Column(name="rol")
private String rol;
public Integer getId_user() {
return id_user;
}
public void setId_user(Integer id_user) {
this.id_user = id_user;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRol() {
return rol;
}
public void setRol(String rol) {
this.rol = rol;
}
public User() {
}
}

MultiTenancy with Hibernate 4.0 with Separate Schema approach

I am using EJB 3.0 and Hibernate 4 with PostgreSQL as my database server to create a multitenant system where each tenant will have separate but identical schema. I am still in the trial stage where I have 3 schemes public, company1, company2 all having a single table person. Now what i want to do is change the schema in runtime as per the user so that he can view the data of his/her company only.
Here is my sample code:
Entity Object:
package com.neebal.domain;
import java.io.Serializable;
import java.lang.Long;
import java.lang.String;
import javax.persistence.*;
import org.eclipse.persistence.annotations.Multitenant;
import org.eclipse.persistence.annotations.MultitenantType;
#Entity
//#Table(schema = "company1")
public class Person implements Serializable {
#Id
private Long id;
private String name;
private static final long serialVersionUID = 1L;
public Person() {
super();
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
The MultiTenantConnectionProvider class:
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.service.config.spi.ConfigurationService;
import org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider;
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
public class MultiTenantProvider implements MultiTenantConnectionProvider, ServiceRegistryAwareService {
private static final long serialVersionUID = 4368575201221677384L;
private C3P0ConnectionProvider connectionProvider = null;
#Override
public boolean supportsAggressiveRelease() {
return false;
}
#Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
connectionProvider = new C3P0ConnectionProvider();
connectionProvider.injectServices(serviceRegistry);
connectionProvider.configure(lSettings);
}
#Override
public boolean isUnwrappableAs(Class clazz) {
return false;
}
#Override
public <T> T unwrap(Class<T> clazz) {
return null;
}
#Override
public Connection getAnyConnection() throws SQLException {
final Connection connection = connectionProvider.getConnection();
return connection;
}
#Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
try {
connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
}
catch (SQLException e) {
throw new HibernateException("Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e);
}
return connection;
}
#Override
public void releaseAnyConnection(Connection connection) throws SQLException {
try {
connection.createStatement().execute("SET SCHEMA 'public'");
}
catch (SQLException e) {
throw new HibernateException("Could not alter JDBC connection to specified schema [public]", e);
}
connectionProvider.closeConnection(connection);
}
#Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
releaseAnyConnection(connection);
}
}
The CurrentTenantIdentifierResolver class:
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
public class SchemaResolver implements CurrentTenantIdentifierResolver {
#Override
public String resolveCurrentTenantIdentifier() {
System.out.println("company1");
return "company1"; //TODO: Implement service to identify tenant like: userService.getCurrentlyAuthUser().getTenantId();
}
#Override
public boolean validateExistingCurrentSessions() {
return false;
}
}
The persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<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="testEJB">
<jta-data-source>jdbc/testpgsql</jta-data-source>
<properties>
<property name="javax.persistence.provider" value="org.hibernate.ejb.HibernatePersistence" />
<property name="hibernate.connection.username" value="postgres" />
<property name="hibernate.connection.password" value="root" />
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/test" />
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.multiTenancy" value="SCHEMA" />
<property name="hibernate.tenant_identifier_resolver" value="com.neebal.util.multitenancy.SchemaResolver" />
<property name="hibernate.multi_tenant_connection_provider"
value="com.neebal.util.multitenancy.MultiTenantProvider" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
And finally the DAO class:
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.neebal.domain.Person;
/**
* Session Bean implementation class PersonDAO
*/
#Stateless
public class PersonDAO implements PersonDAOLocal {
#PersistenceContext
EntityManager entityManager;
/**
* Default constructor.
*/
public PersonDAO() {
// TODO Auto-generated constructor stub
}
#Override
public void save(Person person) {
entityManager.persist(person);
}
#Override
public List<Person> getAll() {
Person person = entityManager.find(Person.class, 2L);
System.out.println(person.getName());
return null;
}
}
In this example I have hardcoded the schema as company1 but it still persists or retrieves the data from public schema. So where am I wrong in this example.
The question is already 1 year old, but I think the problem of using different schemas depending on some runtime condition is common one, so I'll answer anyway. If I understand you right and the set of tenants is small, then I think the easiest way to do what you're trying to achieve is to define a separate persistence units for each tenant in your persistence.xml
<persistence-unit name="public">
.. settings for first schema
</persistence-unit>
<persistence-unit name="company1">
.. settings for first schema
</persistence-unit>
<persistence-unit name="company2">
.. settings for first schema
</persistence-unit>
Then have for each one a separate entityManager:
#PersistenceContext(unitName = "public")
private EntityManager emPublic;
#PersistenceContext(unitName = "company1")
private EntityManager emComp1;
#PersistenceContext(unitName = "company2")
private EntityManager emComp1;
Now you can switch between entity managers, given the currently authorized user.
Depending on your exact infrastructure etc, there may be other approaches, too. For instance, if all your schemas are on the same server, then you could also try to pass the schema names directly to your queries.
This is pure JPA and thus portable and not depending on any persistence provider like hibernate nor on your DBMS.

I'm not getting any error, then why is not my data persisting into the database?

Greetings my folks I'm using JPA 2.0 and so far I'm not really getting any kind of error from anywhwere in the project, however the data is not persiting into the database at all, this is my persistence.xml (just the pu) file as it looks right now:
<persistence-unit name="auto-core-pu" transaction-type="RESOURCE_LOCAL">
<description>Auto Core Persistence Unit</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.auto.core.model.Cars</class>
<class>com.auto.core.model.Client</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/auto_core"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>
This is my EntityManagerClient.class
package com.auto.core.persistence;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import com.auto.core.model.Cars;
public class EntityManagerClient {
public static void main(String[] args){
EntityManager em = Persistence.createEntityManagerFactory("auto-core-pu").createEntityManager();
EntityTransaction t = em.getTransaction();
t.begin();
Cars cr = new Cars();
cr.setBrand("Toyota");
cr.setModel("Camry");
cr.setEngine("V6");
cr.setDoors(5);
cr.setType("Jeepeta");
cr.setYear(123);
cr.setDescription("Auto usado del año 123 D.C.");
t.commit();
}
public static void getData(){
EntityManager em = Persistence.createEntityManagerFactory("auto-core-pu").createEntityManager();
EntityTransaction g = em.getTransaction();
g.begin();
Cars cr = em.createNamedQuery("Cars.FindbyId", Cars.class).setParameter("id", 1L).getSingleResult();
System.out.println(cr.getBrand());
}
}
and lass an example of how I did the annotations in other classes:
#Entity
#Table(schema="auto_core" , name="client")
public class Client {
#Id
#GeneratedValue
long id;
#Column(name="name")
String name;
#Column(name="lastname")
String lastname;
#Column(name="email")
String email;
#Column(name="address")
String address;
#Column(name="address2")
String address2;
#Column(name="zip")
String zip;
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;
}
Again, I'm not getting any kind of error, is just that I can't persist data, or query data that I put manually into the database, that's all.
It's because you're getting the EntityManager, opening the transaction, and creating the object but you don't persist it. You have to invoke:
em.persist(cr);
before
t.commit();
Until you persist it, it's just a POJO in memory.

Categories

Resources