I am trying to learn JPA
Here is my entity file.
Passenger.java
#Entity
public class Passenger implements Serializable{
public Passenger() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String firstName;
private String lastName;
}
My persistence.xml is below.
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="JPA_POJO">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/airlines</jta-data-source>
<class>com.airline.model.Passenger</class>
</persistence-unit>
My servlet is like this.
#WebServlet(name = "addPassenger")
public class addPassenger extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Passenger p = new Passenger();
// airline p = new airline();
p.setFirstName("ABC");
p.setLastName("XYZ");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA_POJO");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
}
}
When I run this code I get the following error.
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'airline.passenger' doesn't exist
Error Code: 1146
Call: INSERT INTO PASSENGER (ID, FIRSTNAME, LASTNAME) VALUES (?, ?, ?)
As far as I can understand it is trying to connect to PASSENGER table instead of AIRLINE table.
I have assigned the data source that points to airline table. In fact I wrote a class file airline.java basically same as Passenger.java, when I used airline.java object(commented out in code) in my servlet it worked.
What am I doing wrong?
What it does seem to be totally expected, you did not provide a name to the table of your entity Passenger so it uses the name of the entity as default table name so it tries to insert into the table Passenger of the schema airline which is what is expected.
For me your problem is only that the table has not been created so far, if you want let eclipselink create your table for you, you should add the property eclipselink.ddl-generation to your file persistence.xml and set it to create-or-extend-tables as described here.
In your case it will be something like:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="JPA_POJO">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/airlines</jta-data-source>
<class>com.airline.model.Passenger</class>
<properties>
<property name="javax.persistence.jtaDataSource" value="java:/airlines"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
</properties>
</persistence-unit>
</persistence>
Related
I have created a PostgreSQL script just to insert a row in the customer table. The insert happens when my project is starting to run.
But it doesn't work because I'm getting the following error:
[EL Warning]: 2016-10-23 22:14:40.182--ServerSession(609762439)--?>Exception [EclipseLink-4002] (Eclipse Persistence Services - >2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax >error at end of input
Position: 82 Error Code: 0 Call: INSERT INTO customer (id, Name, Adres, PostalCode, City, Tel, >Fax, Number) VALUES Query: DataModifyQuery(sql="INSERT INTO customer (id, Name, Adres, >PostalCode, City, Tel, Fax, Number) VALUES") [EL Warning]: 2016-10-23 22:14:40.183--ServerSession(609762439)-->Exception [EclipseLink-4002] (Eclipse Persistence Services - >2.5.2.v20140319-9ad6abd): >org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax >error at or near "1"
Position: 2 Error Code: 0 Call: (1, 'Kantoor Snel Transport / Distributiecentrum', >'Zeugstraat', '2801JD', 'Gouda', 182512784, NULL, '92'); Query: DataModifyQuery(sql="(1, 'Kantoor Snel Transport / >Distributiecentrum', 'Zeugstraat', '2801JD', 'Gouda', 182512784, NULL, >'92');") [EL Info]: connection: 2016-10-23 22:15:02.917-->ServerSession(609762439)-->file:/C:/Users/yomac_000/workspace/.metadata/.plugins/org.eclipse.wst.ser>ver.core/tmp0/wtpwebapps/snel-transport/WEB-INF/classes/_snel-transport >logout successful
Here is the persistence.xml file:
<?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="snel-transport" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>nl.cimsolutions.snel_transport.models.Orders</class>
<class>nl.cimsolutions.snel_transport.models.OrderLine</class>
<class>nl.cimsolutions.snel_transport.models.OrderList</class>
<class>nl.cimsolutions.snel_transport.models.Customer</class>
<class>nl.cimsolutions.snel_transport.models.Product</class>
<class>nl.cimsolutions.snel_transport.models.Category</class>
<class>nl.cimsolutions.snel_transport.models.Status</class>
<class>nl.cimsolutions.snel_transport.models.Truck</class>
<!-- <jta-data-source>java:app/snel-transport</jta-data-source> -->
<!-- <exclude-unlisted-classes>false</exclude-unlisted-classes> -->
<properties>
<property
name="javax.persistence.schema-generation.database.action"
value="drop-and-create" />
<property name="eclipselink.canonicalmodel.subpackage"
value="dev" />
<property name="javax.persistence.sql-load-script-source"
value="META-INF/sql/Customer2.sql" />
<property name="javax.persistence.schema-generation-target"
value="database" />
<property name="javax.persistence.jdbc.driver"
value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/snel-transport" />
<property name="javax.persistence.jdbc.user" value="transport_user" />
<property name="javax.persistence.jdbc.password"
value="admin" />
<property name="javax.persistence.jdbc.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
And here is my PostgreSQL script:
INSERT INTO customer (id, Name, Adres, PostalCode, City, Tel, Fax, Number) VALUES
(1, 'Kantoor Snel Transport / Distributiecentrum', 'Zeugstraat', '2801JD', 'Gouda', 182512784, NULL, '92');
And here is how the Customer model looks like:
#Entity
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#TableGenerator(
name = "CustomerGenerator",
allocationSize = 1,
initialValue = 1)
#Id
#GeneratedValue(strategy = GenerationType.TABLE,
generator="CustomerGenerator")
private Long id;
private String name;
private String adres;
#Column(name="Number")
private String streetNumber;
#Column(name="PostalCode")
private String postalCode;
#Column(name="City")
private String city;
#Column(name="Tel")
private String tel;
#Column(name="Fax")
private String fax;
#OneToMany(mappedBy = "customer", targetEntity = Orders.class)
private List<Orders> orders;
public Customer() {
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(String streetNumber) {
this.streetNumber = streetNumber;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public String toString() {
return "model.OrderLine[ id=" + id + " ]";
}
public String getName() {
return name;
}
public String getAdres() {
return adres;
}
public void setName(String name) {
this.name = name;
}
public void setAdres(String adres) {
this.adres = adres;
}
}
I have already tried using the PostgreSQL script in pgAdmin. And there the script works, but somehow it doesn't work in JPA.. Anyone got a clue how I can solve this problem?
I am overlooking some aspect of the setup but I don't know where to look. Eclipse, Tomcat, and MySQL. In the servlet I have an exception: No Persistence provider for EntityManager named EmployeeService. MySQL server is running and I configured a connection for the project. I have eclipselink jar library in the build path. What can I check to get it working?
Employee.java
package servlet;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="employee")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
private String name;
private double salary;
public Employee() { }
public Employee(int id){ this.id = id; }
public int getId() { return this.id; }
public void setId(int id) { this.id = id; }
public String getName(){ return this.name; }
public void setName(String name){ this.name = name; }
public double getSalary(){ return salary; }
public void setSalary(double salary){ this.salary = salary; }
public String toString(){ return "Employee: " + name; }
}
EmployeeService.java
package servlet;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
public class EmployeeService {
protected EntityManager em;
public EmployeeService(EntityManager em){
this.em = em;
}
public Employee createEmployee(int id, String name, Double salary){
Employee emp = new Employee(id);
emp.setName(name);
emp.setSalary(salary);
em.persist(emp);
return emp;
}
public List<Employee> findAllEmployees(){
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e", Employee.class);
return query.getResultList();
}
}
Relevant servlet code
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();
EmployeeService service = new EmployeeService(em);
String name = request.getParameter("name");
em.getTransaction().begin();
Employee emp = service.createEmployee(158, name, 279445.00);
em.getTransaction().commit();
System.out.println(emp);
List<Employee> list = service.findAllEmployees();
for(Employee e : list){
System.out.println(e);
}
}
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="4_WEB_JPA" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>servlet.Employee</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/company"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>
</persistence>
You can initiate EntityManagerFactory by
EntityManagerFactory emf = Persistence.createEntityManagerFactory("4_WEB_JPA");
because your persistent unit named 4_WEB_JPA in your persistent.xml.
I am new to Hibernate (implementing since yesterday) and i succesfully created a method, that transfers my Customer Objects to the Database.
After i quit my application and start it again and create a new session (in an other method) based on my hibernate.cfg.xml file with this setting:
<property name="hibernate.hbm2ddl.auto">create</property>
It leads to that point, that all relevant tables, created with Hibernate are being deleted.
So maybe that is a comprehension question, but i think "transparent persistence by hibernate" means also, that my POJO's are persistent beyond the runtime of my application!?
So i read several topics on Stackoverflow and tried it with this setting:
<property name="hibernate.hbm2ddl.auto">update</property>
But this leads to SQL errors:
com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
Of course i don't want have duplicates, so i suppose that hibernate doesn't send a SQL Statement referring to an existing object.
It sends a Statement like this:
UPDATE `customer` SET `id`=1,`birthday`='1990-10-05 00:00:00',`forename`='TestCustomer',`gender`='F',`generatedProfitsLastYear`='0',`generatedProfitsTotal`='0',`surename`='A',`gcid`='1'
But i need the same statement, with a
Where `id`=1
at the end.
So basically what i want is, that hibernate doesn't drop all the tables and creates it again when i restart my application and create a new session based on the configuration file. So after i open a new session, i can transfer the Customer Objects stored in the database to POJOs.
Did i understand the concept of hibernate incorrectly or am i making a typical beginners mistake?
Below you will find my Customer Class:
#Entity
#Table(name="CUSTOMER")
public class Customer {
private int id;
private String forename;
private String surname;
private char gender;
private Date birthday;
private double generatedProfitsTotal;
private double generatedProfitsLastYear;
private CustomerGroup assignedTo;
public Customer(int id, String forename, String surname, char gender,
Date birthday) {
super();
this.id = id;
this.forename = forename;
this.surname = surname;
this.gender = gender;
this.birthday = birthday;
}
#Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "forename")
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
#Column(name = "surename")
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Column(name = "gender")
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
#Column(name = "birthday")
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
#Column(name = "generatedProfitsTotal")
public double getGeneratedProfitsTotal() {
return generatedProfitsTotal;
}
public void setGeneratedProfitsTotal(double generatedProfitsTotal) {
this.generatedProfitsTotal = generatedProfitsTotal;
}
#Column(name = "generatedProfitsLastYear")
public double getGeneratedProfitsLastYear() {
return generatedProfitsLastYear;
}
public void setGeneratedProfitsLastYear(double generatedProfitsLastYear) {
this.generatedProfitsLastYear = generatedProfitsLastYear;
}
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="gcid", nullable=true, insertable=true, updatable=true)
public CustomerGroup getAssignedTo() {
return assignedTo;
}
public void setAssignedTo(CustomerGroup assignedTo) {
this.assignedTo = assignedTo;
}
}
my hibernate config file:
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1/hibernatetesting</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="studyproject.Customer"/>
<mapping class="studyproject.CustomerGroup"/>
<mapping class="studyproject.BonusPackage"/>
</session-factory>
</hibernate-configuration>
Thanks
try session.saveOrUpdate() method where you have used session.save() it will prevent your database from dropping while fetching data use it with hbm2ddl.auto update. it worked for me. hope it helps.
What did you do where the 'duplicate error' occurs? Now I have the hibernate.hbm2ddl.auto configured as yours, but it's okay saving or updating entity in my local.
I try to run a basic application with hibernate and jpa, but now I'm stuck on this exception when running app...Here's the code and erro below:
java.lang.IllegalArgumentException: Not an entity: class pka.EclipseJPAExample.domain.Employee
at org.hibernate.ejb.metamodel.MetamodelImpl.entity(MetamodelImpl.java:158)
at org.hibernate.ejb.criteria.QueryStructure.from(QueryStructure.java:136)
at org.hibernate.ejb.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:177)
at pka.EclipseJPAExample.jpa.JpaTest.createEmployees(JpaTest.java:47)
at pka.EclipseJPAExample.jpa.JpaTest.main(JpaTest.java:33)
JpaTest.java:
public class JpaTest {
private EntityManager manager;
public JpaTest(EntityManager manager) {
this.manager = manager;
}
/**
* #param args
*/
public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistenceUnit");
EntityManager manager = factory.createEntityManager();
JpaTest test = new JpaTest(manager);
EntityTransaction tx = manager.getTransaction();
tx.begin();
try {
test.createEmployees();
} catch (Exception e) {
e.printStackTrace();
}
tx.commit();
test.listEmployees();
System.out.println(".. done");
}
private void createEmployees() {
CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<Employee> query = builder.createQuery(Employee.class);
query.from(Employee.class);
int numOfEmployees = manager.createQuery(query).getResultList().size();
if (numOfEmployees == 0) {
Department department = new Department("java");
manager.persist(department);
manager.persist(new Employee("Jakab Gipsz",department));
manager.persist(new Employee("Captain Nemo",department));
}
}
private void listEmployees() {
CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<Employee> query = builder.createQuery(Employee.class);
query.from(Employee.class);
List<Employee> resultList = manager.createQuery(query).getResultList();
for (Employee next : resultList) {
System.out.println("next employee: " + next);
}
}
}
and persistence.xml:
....<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/testowa" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="enchantsql" />
<property name="hbm2ddl.auto" value="create" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>....
Could you point where is the problem?
EDIT:
I forgot to paste Employee class...so here it is below:
#Entity
#Table(name="Employee")
public class Employee {
#Id
#GeneratedValue
private Long id;
private String name;
#ManyToOne
private Department department;
public Employee() {}
public Employee(String name, Department department) {
this.name = name;
this.department = department;
}
public Employee(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department="
+ department.getName() + "]";
}
}
As you can see it is mapped.
Make sure #Entity annotation in your entity. You also need to configure an entity in persistence.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<class>pka.EclipseJPAExample.domain.Employee</class>
If you have numerous ENTITY classes in your application, adding an entry for every entity in "persistence.xml" won't be a good choice.
Instead, create your own data source bean using Custom AutoConfiguration.
Use LocalContainerEntityManagerFactoryBean inside dataSource bean Creation method.
Here, you need to define
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new
LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setPackagesToScan("org.springframework.boot.entities");
This package is the location where all entity classes have been saved.
Thus no need to define every single entry for Entity classes at "persistence.xml".
Prefer Spring-based Scanning.
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.