I am newbie with JPA and Hibernate. I have the two entities, Vendor and Product, described below.
#Entity
public class Vendor extends BaseEntity
{
private static final long serialVersionUID = 267250313080292374L;
#NotNull
private String name;
#NotNull
private String city;
#OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL)
private List<Product> products = new ArrayList<Product>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
#Entity
public class Product extends BaseEntity
{
private static final long serialVersionUID = -4676899182130380017L;
#NotNull
private String name;
#Column(nullable = false, precision = 10, scale = 2)
private double price;
#NotNull
private int quantity;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="VENDOR_ID", nullable = false)
private Vendor vendor;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Vendor getVendor() {
return vendor;
}
public void setVendor(Vendor vendor) {
this.vendor = vendor;
}
}
My problem is related to the usage of the attribute nullable = false in the #ManyToOne annotation. I want that the corresponding column annotated with #ManyToOne to be not null. However when I test the persitence of the entities with the following test:
public void testCreateEntity()
{
// create vendor1, set name and city
vendor1 = new Vendor();
vendor1.setName("MediaMarkt");
vendor1.setCity("Berlin");
vendor1 = service.createOrUpdateEntity(vendor1);
// create product1, set name, price and quantity
product1 = new Product();
product1.setName("Samsung Galaxy S7");
product1.setPrice(new Double("819.00"));
product1.setQuantity(1);
vendor1.getProducts().add(product1);
product1.setVendor(vendor1);
// create product at service
product1 = service.createOrUpdateEntity(product1);
...
}
where the createOrUpdateEntity method is part of a DAO Bean Object
#PersistenceContext
private EntityManager em;
public <T extends BaseEntity> T createOrUpdateEntity(T entity)
{
// as we have no id yet, it must be freshly brewed
if (entity.getId() == 0)
{
log.debug("createOrUpdateEntity::create:: {}", entity);
this.em.persist(entity);
}
// if there is an id, we must have dealt with it before
else
{
log.debug("createOrUpdateEntity::update:: {}", entity);
this.em.merge(entity);
}
this.em.flush();
return entity;
}
I get the error:
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: de.brockhaus.stock.entity.Stock
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:765)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:758)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:425)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:249)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
... 138 more
EDIT: Implementing this example, which uses a #ManyToOne column annotated as nullable = false, I have realized that my problem is not related to this. Such as shown in the previous server log, the problem is being caused by the Cascade class. Some solutions in SO suggest to change CascadeType.ALL by CascadeType.MERGE. Other ones show different strategies. Even some ones tell that only the OneToMany side of the association should use cascade. Frankly, I thought that using CascadeType.ALL in both sides of the association was the best option. But it seems that I was wrong. Although, such as I have pointed out, I am newbie with JPA and Hibernate and I do not understand the reasonings.
You can use optional tag for null control:
#ManyToOne(cascade = CascadeType.ALL, optional = false)
#JoinColumn(name="VENDOR_ID")
private Vendor vendor;
Actually, with this code, I can get your example to work:
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>demo</groupId>
<artifactId>hibernate4-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernate4-demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hibernate-core.version>4.3.11.Final</hibernate-core.version>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
BaseEntity.java (curtesy of Brockhaus)
package demo.hibernate4;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
#MappedSuperclass
public abstract class BaseEntity implements Serializable {
#Version
private long version;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Temporal(TemporalType.DATE)
private Date creationDate;
public BaseEntity() {
//lazy
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public long getId() {
return id;
}
}
GenericDAOBean.java
package demo.hibernate4;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
public class GenericDAOBean {
private EntityManager em;
#Override
public <T extends BaseEntity> T createOrUpdateEntity(T entity) {
if (entity.getId() == 0) {
this.em.persist(entity);
} else {
this.em.merge(entity);
}
this.em.flush();
return entity;
}
public void setEm(EntityManager em) {
this.em = em;
}
}
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="hibernate4-demo" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mysql?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="javax.persistence.schema-generation.database.action" value="none"/>
</properties>
</persistence-unit>
</persistence>
Main.java
package demo.hibernate4;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate4-demo");
EntityManager em = emf.createEntityManager();
GenericDAOBean service = new GenericDAOBean();
service.setEm(em);
EntityTransaction transaction = em.getTransaction();
transaction.begin();
// create vendor1, set name and city
Vendor vendor1 = new Vendor();
vendor1.setName("MediaMarkt");
vendor1.setCity("Berlin");
vendor1 = service.createOrUpdateEntity(vendor1);
// create product1, set name, price and quantity
Product product1 = new Product();
product1.setName("Samsung Galaxy S7");
product1.setPrice(new Double("819.00"));
product1.setQuantity(1);
vendor1.getProducts().add(product1);
product1.setVendor(vendor1);
// create product at service
product1 = service.createOrUpdateEntity(product1);
transaction.commit();
System.exit(0);
}
}
With this code and your mapping, I get 2 rows in MySQL and the relationship between the Product and the Vendor is established.
However, I don't understand what you're trying to achieve with your list of vendor keys. For the moment, the table PRODUCT_VENDORKEY stays empty.
You'll have to describe your context further.
Related
After starting the program (launching TomCat) there are no tables created in the schema, but the table "player" has to be created automatically.
I checked hibernate config, but can't find where is the problem.
I've tried changing hbm2ddl.auto to hibernate.hbm2ddl.auto (also create, create-drop etc.) but it didn't help.
If there are any ideas, please let me know. Thanks.
Entity class:
package com.game.entity;
import javax.persistence.*;
import java.util.Date;
#Entity
#Table(schema = "rpg", name = "player")
public class Player {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name", length = 12, nullable = false)
private String name;
#Column(name = "title", length = 30, nullable = false)
private String title;
#Column(name = "race", nullable = false)
#Enumerated(EnumType.ORDINAL)
private Race race;
#Column(name = "profession", nullable = false)
#Enumerated(EnumType.ORDINAL)
private Profession profession;
#Column(name = "birthday", nullable = false)
private Date birthday;
#Column(name = "banned", nullable = false)
private Boolean banned;
#Column(name = "level", nullable = false)
private Integer level;
public Player() {
}
public Player(Long id, String name, String title, Race race, Profession profession, Date birthday, Boolean banned, Integer level) {
this.id = id;
this.name = name;
this.title = title;
this.race = race;
this.profession = profession;
this.birthday = birthday;
this.banned = banned;
this.level = level;
}
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 String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Race getRace() {
return race;
}
public void setRace(Race race) {
this.race = race;
}
public Profession getProfession() {
return profession;
}
public void setProfession(Profession profession) {
this.profession = profession;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Boolean getBanned() {
return banned;
}
public void setBanned(Boolean banned) {
this.banned = banned;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
}
Repository class:
package com.game.repository;
import com.game.entity.Player;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.NativeQuery;
import org.springframework.stereotype.Repository;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Optional;
#Repository(value = "db")
public class PlayerRepositoryDB implements IPlayerRepository {
private final SessionFactory sessionFactory;
public PlayerRepositoryDB() {
Configuration configuration = new Configuration().configure().addAnnotatedClass(Player.class);
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
#Override
public List<Player> getAll(int pageNumber, int pageSize) {
try(Session session = sessionFactory.openSession()){
NativeQuery<Player> nativeQuery = session.createNativeQuery("SELECT * FROM rpg.player", Player.class);
nativeQuery.setFirstResult(pageNumber * pageSize);
nativeQuery.setMaxResults(pageSize);
return nativeQuery.list();
}
}
Hibernate configuration:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/rpg</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">1234</property>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
Full project code with pom.xml is available by link:
https://github.com/gamlethot/project-hibernate-1
1-Hibernate does not recognize your repository. You should not mark repo classes as #Repository because they are not interfaces and in your example they are working like a service. So they can be #Service.
2-Do not implement IPlayerRepository. Mark it as #Repository and just autowire it to your service classes (or use constructor injection and just use like a variable)
Like:
#Service
public class PlayerRepositoryDB {
private IPlayerRepository playerRepository;
public PlayerRepositoryDB (IPlayerRepository playerRepository){ //CONSTRUCTOR
this.playerRepository = playerRepository;...
3- DB repository classes are implementing IPlayerRepository but it must be marked as #Repository and It should extend either CrudRepository or JpaRepository (which extends CrudRepository already).
Like:
#Repository
public interface IPlayerRepository extends JpaRepository<Player, Long> {
//Here are the methods;
}
Here, the Long is the type of primary key of Player class.
Hibernate XML:
<property name="hibernate.connection.CharSet">utf8mb4</property>
<property name="hibernate.connection.characterEncoding">UTF-8</property>
<property name="hibernate.connection.useUnicode">true</property>
Connection url:
db.url=jdbc:mysql://localhost:3306/db_name?useUnicode=true&character_set_server=utf8mb4
As a side note I would like to make one clarification that UTF-8 is the character encoding while utf8mb4 is a character set that MySQL supports. MySQL's utf8mb4 is a superset to MySQL's utf8.
Spring/Hibernate filter:
<form accept-charset="UTF-8">
Problem solved.
It was because of javax.persistence.; import instead of
jakarta.persistence. in entity class.
I have 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.vyhn</groupId>
<artifactId>jpa</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>jpa Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.2</version>
</dependency>
</dependencies>
<build>
<finalName>jpa</finalName>
</build>
</project>
Employee.java
package example.com.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
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() + "]";
}
}
Department.java
package example.com.domain;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
#Entity
public class Department {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "department", cascade = CascadeType.PERSIST)
private List<Employee> employees = new ArrayList<Employee>();
public Department() {
super();
}
public Department(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 List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
JpaTest.java
package example.com.jpa;
import example.com.domain.Department;
import example.com.domain.Employee;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
public class JpaTest {
private EntityManager manager;
public JpaTest(EntityManager manager) {
this.manager = manager;
}
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() {
int numOfEmployees = manager.createQuery("Select a From Employee a", Employee.class).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() {
List<Employee> resultList = manager.createQuery("Select a From Employee a", Employee.class).getResultList();
System.out.println("num of employess:" + resultList.size());
for (Employee next : resultList) {
System.out.println("next employee: " + next);
}
}
}
When I run JpaTest.java, has error:
"C:\Program Files\Java\jdk1.8.0_92\bin\java" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_92\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_92\jre\lib\rt.jar;C:\Users\Administrator\IdeaProjects\demo_jpa\target\classes;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\eclipselink\2.6.3\eclipselink-2.6.3.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\javax.persistence\2.1.1\javax.persistence-2.1.1.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\commonj.sdo\2.1.1\commonj.sdo-2.1.1.jar;C:\Users\Administrator\.m2\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;C:\Users\Administrator\.m2\repository\org\glassfish\javax.json\1.0.4\javax.json-1.0.4.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.core\2.6.3\org.eclipse.persistence.core-2.6.3.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.asm\2.6.3\org.eclipse.persistence.asm-2.6.3.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.jpa\2.6.3\org.eclipse.persistence.jpa-2.6.3.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.antlr\2.6.3\org.eclipse.persistence.antlr-2.6.3.jar;C:\Users\Administrator\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.jpa.jpql\2.6.3\org.eclipse.persistence.jpa.jpql-2.6.3.jar;C:\Users\Administrator\.m2\repository\javax\persistence\persistence-api\1.0.2\persistence-api-1.0.2.jar;C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\6.0.2\mysql-connector-java-6.0.2.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.2\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain example.com.jpa.JpaTest
Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named persistenceUnit
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at example.com.jpa.JpaTest.main(JpaTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Help me fix this error, thank you!
You have to put persistence.xml in java/resources folder.
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
I hope this will work
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.
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() {
}
}
I can't figure out what the problem is, please help. I've searched a lot, but didn't find any useful advice. Maybe you can help me. Thanks a lot.
There are two classes using eclipselink as jpa provider:
#Entity
#Table(name = "USER")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
private String login;
private Long groupId;
private String email;
#ManyToMany(mappedBy = "users")
private List polls;
#OneToMany(mappedBy = "user")
private List votes;
public List getVotes() {
return votes;
}
public void setVotes(List votes) {
this.votes = votes;
}
public User() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public Long getGroupId() {
return groupId;
}
public void setGroupId(Long groupId) {
this.groupId = groupId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List getPolls() {
return polls;
}
public void setPolls(List polls) {
this.polls = polls;
}
}
and
#Entity
#Table(name = "VOTE")
public class Vote {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long vid;
private String comment;
#ManyToOne
private User user;
#ManyToOne
private Option option;
public Vote() {
}
public Long getVid() {
return vid;
}
public void setVid(Long vid) {
this.vid = vid;
}
#Column(name = "comment")
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Option getOption() {
return option;
}
public void setOption(Option option) {
this.option = option;
}
}
When I'm trying to compile this, I receive error:
Exception [EclipseLink-7214] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The target entity of the relationship attribute [votes] on the class [class logic.User] cannot be determined. When not using generics, ensure the target entity is defined on the relationship mapping.
Here is my persistence.xml file:
<?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="pollsPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>logic.Option</class>
<class>logic.Poll</class>
<class>logic.User</class>
<class>logic.Vote</class>
<class>logic.Greeting</class>
<properties>
<property name="eclipselink.jdbc.password" value="" />
<property name="eclipselink.jdbc.user" value="" />
<property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="eclipselink.jdbc.url"
value="jdbc:mysql://localhost:3306/core_polls" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.logging.level" value="INFO" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
</properties>
</persistence-unit>
</persistence>
As stated in the Javadoc
If the collection is defined using generics to specify the element
type, the associated target entity type need not be specified;
otherwise the target entity class must be specified.
So, you can do either
#OneToMany(mappedBy = "user")
private List<Vote> votes;
or
#OneToMany(targetEntity=logic.Vote.class, mappedBy = "user")
private List votes;
But I would prefer the first.