We are building a REST application using JPA which we have trouble getting to work properly.
The issue is that when doing updates or adding items jpa selects starts returning multiple versions of the changed. For example if Item contains A and is changed to B then changed to C, select queries will return A first run, B second, C third, A fourth etc. Sometimes it wont show directly but holding down f5 on the browser for GET items resource then changing the data always generates this problem.
Ive created a clean sample project which demonstrates this. We use Glassfish 4.1.0 (since there were som other issues with 4.1.1).
Created mysql database 'testdb' Created a table 'item' containing two VARCHAR(45) fields, 'firstName' and 'lastName'.
Created a new maven project based on 'javaee7-essentials-acrhetype'. (https://github.com/AdamBien/javaee7-essentials-archetype)
Added datasource in intellij and generated an Entity bean for this Item entity. Adjusted persistence.xml to include username and password.
Created a simple DTO / Pojo class to receive the PUT data.
Created an ItemResource class.
All in all 4 classes and persistence.xml + pom.xml
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test.server</groupId>
<artifactId>testdb</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.11.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
</dependencies>
<build>
<finalName>testdb</finalName>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
</project>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="LocalUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.server.entities.ItemEntity</class>
<properties>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/testdb"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="abc123" />
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
ItemDTO
public class ItemDTO {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
ItemEntity bean (added the namedqueries manually)
#Entity
#NamedQueries({
#NamedQuery(name = "Item.All", query = "SELECT item from ItemEntity item"),
#NamedQuery(name = "Item.Get", query = "SELECT item from ItemEntity item WHERE item.id = :id")
})
#Table(name = "item", schema = "testdb", catalog = "")
public class ItemEntity {
private Integer id;
private String firstName;
private String lastName;
#Id
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Basic
#Column(name = "firstName")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Basic
#Column(name = "lastName")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemEntity that = (ItemEntity) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false;
if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
}
ItemResources class
#Path("items")
public class ItemResources {
private static EntityManagerFactory emf = null;
public ItemResources() {
if(emf == null) {
emf = Persistence.createEntityManagerFactory("LocalUnit");
}
}
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getAllAccounts() {
EntityManager manager = getEntityManager();
Collection<ItemEntity> accounts = null;
try {
accounts = manager.createNamedQuery("Item.All").getResultList();
} catch(Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
return Response.ok().entity(new GenericEntity<Collection<ItemEntity>>(accounts) {}).build();
}
#PUT
#Path("{id}")
#Consumes(MediaType.APPLICATION_JSON)
public Response updateAccount(#PathParam("id") int id, ItemDTO itemDTO) {
EntityManager manager = getEntityManager();
try {
manager.getTransaction().begin();
TypedQuery<ItemEntity> query = manager.createNamedQuery("Item.Get", ItemEntity.class);
query.setParameter("id", id);
ItemEntity account = query.getSingleResult();
account.setFirstName(itemDTO.getFirstName());
account.setLastName(itemDTO.getLastName());
manager.getTransaction().commit();
} catch(Exception e) {
manager.getTransaction().rollback();
throw new RuntimeException(e);
} finally {
manager.close();
}
return Response.ok().entity("OK").build();
}
}
And the main application class (no web.xml, empty beans.xml)
#ApplicationPath("resources")
public class JAXRSConfiguration extends Application {
}
Summarized this dont work. The problem described in the beginning occurs which makes it impossible to use for anything real. Are we missing something here, shouldnt this simple example work?
We have a real application containing this issue and we have some time trying to find out why it behaves like this. We tried different ways of clearing the cache, evicting the factory, tried changing connection isolation, disabling 2ndlevel and query cache in persistence.xml but still got the same issuein the end or traded for more severe db issues. Tried on two different servers running same glassfish versions. So we are at the point if we have to roll back to pure jdbc/sql to get this working.
HOWEVER strangely i have not yet been able to reproduce the issue when deploying in intellij yet. But when deploying the .war file on any server weve tried so far the issue appears. But when officially depolyed it seems the only way to make it work would be to create a new fctory instance for each request then close it when done. Which seems extremely wasteful.
If anyone could help us solve this and thus avoid alot of refactoring we would be forever greatful :) Are we missing something vital that is needed for this to work?
Related
I have some difficulties with my first experiments with Web Applications.
I’m using
jdk15.0.1
NetBeans 12.0
MySQL 5.7.19
Payara Server 5.201
Windows 10 build 19041.685
When I create a project Web Application ( Java with Maven > Web Application ), I write my Entity Class, but when I try to generate Persistence unit it does not allow me to use the JTA.
Book.java
#XmlRootElement
#Entity
#NamedQueries({
#NamedQuery(name = "Book.findAll", query = "SELECT d FROM Book d")
})
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Book)) {
return false;
}
Book other = (Book) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.mycompany.test201.Book[ id=" + id + " ]";
}
}
I add New>RESTful Web Services from Patterns...
BookResource.java
#RequestScoped
#Path("book")
public class BookResource {
#PersistenceContext(unitName = "test201pu")
private EntityManager em;
// #Context
// private UriInfo context;
/**
* Creates a new instance of BookResource
*/
public BookResource() {
}
#POST
#Transactional
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addBook(#FormParam("aut")String autr, #FormParam("titl")String til) {
Book b=new Book();
b.setAuthor(autr);
b.setTitle(til);
em.persist(b);
}
/**
* Retrieves representation of an instance of com.mycompany.test201.BookResource
* #return an instance of java.lang.String
*/
#GET
#Produces(MediaType.APPLICATION_XML)
public List<Book> getXml() {
Query q=em.createNamedQuery("Book.findAll", Book.class);
return q.getResultList();
}
/**
* PUT method for updating or creating an instance of BookResource
* #param content representation for the resource
*/
#PUT
#Consumes(MediaType.APPLICATION_XML)
public void putXml(String content) {
}
}
I am forced to correct by hand the XML from
transaction-type="RESOURCE_LOCAL" to transaction-type="JTA" .
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="test201pu" transaction-type="JTA">
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test201?zeroDateTimeBehavior=CONVERT_TO_NULL"/>
<property name="javax.persistence.jdbc.user" value="piero"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="my_password"/>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>
Also the checkbox "Include All Entity Classes in ... Module" is always disabled (and the same the other checkbox “Use Java Transaction APIs”)
Finally when I try some transaction, obviously using like JDBC a connection to database MySQL, there’s no tables in database, so I don’t know where the data was stored.
I'm having quite the predicament with my Web Application.
For my school project, we have to migrate from classical JDBC Integration to a JPA Integration. As for myself, I've decided to use Hibernate JPA Framework. I've tried in a main inside a SessionBean, it works there. But whenever I integrate it in a Web Servlet, I noticed it returned empty lists. I've tried displaying the size of the lists with System.out.println().
Anyways, I think the problem might be in my persistence.xml, more specifically the lack of a <jta-data-source>something here</jta-data-source> in it.
Here's my persistence.xml, maybe you could see where I'm having issues :
<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="PERSISTENCE" transaction-type="JTA">
<description>Hibernate JPA Configuration Example</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>JavaBeans.Employee</class>
<class>JavaBeans.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JEEPRJ?serverTimezone=Europe/Paris"/>
<property name="javax.persistence.jdbc.user" value="jee"/>
<property name="javax.persistence.jdbc.password" value="jee"/>
<property name="javax.persistence.jdbc.serverTimezone" value="Europe/Paris"/>
<property name="javax.persistence.jdbc.useSSL" value="false"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
Here's my Session Bean for Employee :
package SessionBeans;
import JavaBeans.Employee;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import javax.persistence.Query;
/**
*
*/
#Stateless
public class EmployeeSB {
#PersistenceContext(name="PERSISTENCE")
EntityManager em;
public List<Employee> getAllEmployees(){
String query = "SELECT e FROM Employee e ";
Query q = em.createQuery(query);
List<Employee> employees = q.getResultList();
if(employees!=null){
System.out.println("it's not null list size : " + q.getResultList().size());
for(Employee emp:employees){
System.out.println("id : " + emp.getId());
}
return employees;
}
System.out.println("it's null");
return employees;
}
And my Employee class :
#Entity
#Table(name = "EMPLOYE")
public class Employee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Integer id;
#Size(max = 255)
#Column(name = "NOM")
public String nom;
#Size(max = 255)
#Column(name = "PRENOM")
public String prenom;
#Size(max = 255)
#Column(name = "TELDOMICILE")
public String telDomicile;
#Size(max = 255)
#Column(name = "TELPORTABLE")
public String telPortable;
#Size(max = 255)
#Column(name = "TELPRO")
public String telPro;
#Size(max = 255)
#Column(name = "ADRESSE")
public String adresse;
#Size(max = 255)
#Column(name = "CODEPOSTAL")
public String codePostal;
#Size(max = 255)
#Column(name = "VILLE")
public String ville;
// #Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
#Size(max = 255)
#Column(name = "EMAIL")
public String email;
public Employee() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getTelDomicile() {
return telDomicile;
}
public void setTelDomicile(String telDomicile) {
this.telDomicile = telDomicile;
}
public String getTelPortable() {
return telPortable;
}
public void setTelPortable(String telPortable) {
this.telPortable = telPortable;
}
public String getTelPro() {
return telPro;
}
public void setTelPro(String telPro) {
this.telPro = telPro;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
public String getCodePostal() {
return codePostal;
}
public void setCodePostal(String codePostal) {
this.codePostal = codePostal;
}
public String getVille() {
return ville;
}
public void setVille(String ville) {
this.ville = ville;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Employee(String nom, String prenom, String telDomicile, String telPortable, String telPro, String adresse, String codePostal, String ville, String email) {
this.nom = nom;
this.prenom = prenom;
this.telDomicile = telDomicile;
this.telPortable = telPortable;
this.telPro = telPro;
this.adresse = adresse;
this.codePostal = codePostal;
this.ville = ville;
this.email = email;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employee)) {
return false;
}
Employee other = (Employee) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "JavaBeans.Employee[ id=" + id + " ]";
}
}
(Don't mind the French haha).
Anyways, if somebody sees why the entity manager is returning empty lists, that would help me a lot and make me understand where I made my stupid mistake.
Thanks a lot guys and have a great day,
Fares.
If you copy/paste the same code of the above session bean inside the servlet, be careful about transaction management. Since session beans manage transactions as their default behavior, as you did you have not to manage them in the beans. However servlets don't have such this behavior, and it's your own responsibility to implement them.
Be notice that it would be an anti-pattern to implement database related jobs inside servlets which belongs to the view layer. The better approach is using session beans for such this functionality and just call them inside the view layer.
I managed to find where the issue is. Buckle up for the ride cause it's gonna be a long one.
In my persistence.xml I never got to define a <jta-data-source></jta-data-source> because I didn't understand it's goal and why we needed to use it.
Since then I have developed a large amount of knowledge and wisdom (not really, basically trial-and-error philosophy).
So. Enough talking. Straight to the answer.
As I said previously the <jta-data-source></jta-data-source> wasn't defined in the persistence.xml in lieu of a huge <properties></properties> section.
Netbeans IDE generates a file in the WEB-INF folder of your directory. It's called glassfish-resources.xml. Our persistence.xml is somewhat binded to it. In the resources file, we define all of our JDBC connection properties. We name it in a pool through a JNDI.
Therefore our new `persistence.xml looks like this:
<?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="m1se_appv2_war_1.0PU" transaction-type="JTA">
<jta-data-source>java:app/DBJEE</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
And the (in)famous glassfish-resources.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysql_JEEPRJ_jeePool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="3306"/>
<property name="databaseName" value="JEEPRJ"/>
<property name="User" value="jee"/>
<property name="Password" value="***"/>
<property name="URL" value="jdbc:mysql://localhost:3306/JEEPRJ?useSSL=false&serverTimezone=Europe/Paris"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="java:app/DBJEE" object-type="user" pool-name="mysql_JEEPRJ_jeePool"/>
</resources>
BTW If you are using MySQL version above 5.7, absolutely define the useSSL property in URL preferably as false if you don't intend to use it.
I'm trying to understand JPA/Hibernate, I'm able to create new database but I don't understand how insert new row in my
database.
This is the code:
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String adress;
private String phoneNumber;
public void setName(String name) {
this.name = name;
}
public void setAdress(String adress) {
this.adress = adress;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public String getAdress() {
return adress;
}
public String getPhoneNumber() {
return phoneNumber;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Person)) {
return false;
}
Person other = (Person) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entinty.Person[ id=" + id + " ]";
}
}
The class that create the database is:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
public class Main {
public static void main(String args[]) {
Person p = new Person();
p.setName("xxx");
p.setAdress("yyy");
p.setPhoneNumber("zzz");
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("testPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.persist(p);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
em.getTransaction().rollback();
}
em.close();
emf.close();
}
}
At this point I have a table with one row (with written "xxx-yyy-zzz"). How can I add new row? Creating new Person doesn't work because it creates new table... I only find solution using Session and SessionFactory but I'm not able to use it, because I can't understand how generate a hibernate.cfg.xml (and in general how to create a session object).
Is There a solution using only EntityManager? Or how can I generate/write a hibernate.cfg.xml file? Is there a way to generate automatically it using netbeans?
EDIT: this is my persistence.xml file. Where do I have to put the ? I put it in the *** zone but it doesn't work...
<?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="testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.Person</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/stackoverflow?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="leonida95."/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
*****
</properties>
</persistence-unit>
</persistence>
Inside your Persistence Unit file you'll have something like
<properties>
<property name="hibernate.connection.url" value="..." />
<property name="hibernate.connection.driver_class" value="..."/>
...
</properties>
To create tables when the EntityManagerFactory is constructed, just add
<property name="hibernate.hbm2ddl.auto" value="create" />
Your code works fine.
You can call persist as many times as you want, and it will add rows to the target table.
em.persist(person1);
em.persist(person2);
...
persist does not create a table.
I am new in jpa and I am tryingg to write and execute a sample founded here:Sample JPA
This is my table created:
Here is my persistance.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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_0.xsd">
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>ir.ac.sbu.testsimplesql1.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/library?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="pass"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hbm2ddl.auto" value="update"/>
</properties>
I have auto generate model class from database:
package ir.ac.sbu.testsimplesql1;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "Employee")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e"),
#NamedQuery(name = "Employee.findById", query = "SELECT e FROM Employee e WHERE e.id = :id"),
#NamedQuery(name = "Employee.findByFistName", query = "SELECT e FROM Employee e WHERE e.fistName = :fistName"),
#NamedQuery(name = "Employee.findByLastName", query = "SELECT e FROM Employee e WHERE e.lastName = :lastName"),
#NamedQuery(name = "Employee.findByDept", query = "SELECT e FROM Employee e WHERE e.dept = :dept")})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "fistName")
private String fistName;
#Column(name = "lastName")
private String lastName;
#Column(name = "dept")
private String dept;
public Employee() {
}
public Employee(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFistName() {
return fistName;
}
public void setFistName(String fistName) {
this.fistName = fistName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employee)) {
return false;
}
Employee other = (Employee) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "ir.ac.sbu.testsimplesql1.Employee[ id=" + id + " ]";
}
}
This is my poem.xml: (Dependencies Tag)
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.8.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
And the last thing is my main function:
public class EmployeeTest {
private static EntityManager em;
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");
em = emf.createEntityManager();
createEmployee(1, "Saint", "Peter", "Engineering");
createEmployee(2, "Jack", " Dorsey", "Imaginea");
createEmployee(3, "Sam", "Fox", "Imaginea");
}
private static void createEmployee(int id, String firstName, String lastName, String dept) {
em.getTransaction().begin();
Employee emp = new Employee();
emp.setId(id);
emp.setFistName(firstName);
emp.setLastName(lastName);
emp.setDept(dept);
em.persist(emp);
em.getTransaction().commit();
}
}
But when I run this code I face with this error:
I have searched this error bud couldn't understand what should I do. I've also visited this link:
Can not find the declaration of element 'persistence'
javax.persistence.PersistenceException - JPA+Hibernate
and alot more similar questions ....
Can anyone please help me to solve this error?
Thanks in advance for your attention.
You can check your XML against the XSD here : http://www.freeformatter.com/xml-validator-xsd.html
Very useful.
Replace the beginning of your xml with:
<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">
I don't know why, but yours is not validated.
Also, you miss the end of the xml, but i guess it's just a copy/paste error.
I currently have an HBase/Hadoop cluster running without issues, and I am fairly familiar with these products. I recently heard about Kundera, and it looks to be a very powerful tool that I would like to use.
However, I cannot seem to find any documentation/tutorials/examples for setting up Kundera with HBase. I have tried some of the materials I happened to come across, but they have failed so egregiously that I am under the impression that it wasn't relevant.
Essentially I don't know where to begin. I'm not worried about somebody explaining to me any kind of advanced level stuff, but I just cannot get this thing configured.
If anybody can point me in the right direction I would greatly appreciate it.
TLDR: I have an HBase cluster running and want to use Kundera with it and I have no clue where to begin whatsoever. Thanks.
You can start here https://github.com/impetus-opensource/Kundera and https://github.com/impetus-opensource/Kundera/wiki
Kundera is JPA compliant , it's pretty easy and straight forward to setup. wiki has enough documentation / examples to get you started. Kundera dev team is very active here as well.
Just create your persistence.xml as shown
https://github.com/impetus-opensource/Kundera/wiki/Common-Configuration
and hbase specific options
https://github.com/impetus-opensource/Kundera/wiki/HBase-Specific-Features
Kundera + Hbase Configuration in Eclipse
Start your Hbase configuration on linux or others
create Dynamic web project
Add the following jar into Libraries of the project
1)asm-4.0.jar
2)cglib-2.1.jar
3)commons-lang-2.5.jar
4)commons-logging-1.1.1.jar
5)hadoop-core-1.0.0.jar
6)hbase-0.94.4.jar
7)jts-1.11.jar
8)kundera-core-2.5.1.jar
9)kundera-hbase-2.5.jar
10)log4j-1.2.16.jar
11)lucene-core-3.5.0.jar
12)xstream-1.3.1.jar
13)zookeeper-3.3.2.jar
Add the persistence.xml file as following
<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="hbase_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<class>com.fvrl.MyObject</class>
<properties>
<property name="kundera.nodes" value="your host ip"/>
<property name="kundera.port" value="port"/>
<property name="kundera.keyspace" value="KunderaExamples"/>
<property name="kundera.dialect" value="hbase"/>
<property name="kundera.client.lookup.class" value="com.impetus.client.hbase.HBaseClientFactory" />
<property name="kundera.client.property" value="yourxmlfilepath" />
<property name="kundera.ddl.auto.prepare" value="update" />
</properties>
</persistence-unit>
</persistence>
Above xml file path must be place in proper place.
Make your Entity Class as below
#Entity
#Table(name = "MyObject", schema = "KunderaExamples#hbase_pu")
#NamedQueries({
#NamedQuery(name="findAll", query="select c from MyObject c")
})
public class MyObject
{
#Id
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getSecondname() {
return secondname;
}
public void setSecondname(String secondname) {
this.secondname = secondname;
}
private String firstname;
private String secondname;
}
Run Your Project through main method
public static void main(String[] args) {
MyObject myObject = new MyObject();
myObject.setId("0006");
myObject.setFirstname("Nirav");
myObject.setSecondname("shah");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hbase_pu");
EntityManager em = emf.createEntityManager();
//Save
HBaseJPAImpl hBaseJPAImpl =new HBaseJPAImpl(em);
hBaseJPAImpl.save(myObject);
//retrive
List<MyObject> list= hBaseJPAImpl.findAllDetails();
for(MyObject myObject1 : list){
System.out.println("Row Id : "+myObject1.getId());
System.out.println("First Name : "+myObject1.getFirstname());
System.out.println("Last Name : "+myObject1.getSecondname());
}
}
HBaseJPAImpl Class is following
public class HBaseJPAImpl implements IHBaseJPA
{
public HBaseJPAImpl(EntityManager em) {
// TODO Auto-generated constructor stub
this.em = em;
}
#Inject protected EntityManager em;
#Transactional
public void save(MyObject myObject)
{
// em.persist(myObject));
EntityTransaction entityTransaction = this.em.getTransaction();
entityTransaction.begin();
em.persist(myObject));
entityTransaction.commit();
}
#SuppressWarnings("unchecked")
#Override
#Transactional
public List<MyObject> findAllDetails()
{
Query query = em.createNamedQuery("findAll");
List<MyObject> results = (List<MyObject>) query.getResultList();
return results;
}
}
interface IHBaseJPA is below
public interface IHBaseJPA
{
void save(MyObject contact);`enter code here`
List<MyObject> findAllDetails();
}
if find any queries on the above then contact me