I have a silly problem with subgraphs. It's my firsttime with EntityGraphs.
I have following classes im my common lib:
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
#MappedSuperclass
public abstract class NamedDomainObjectWithFiles extends NamedDomainObject {
/**
*
*/
private static final long serialVersionUID = 1L;
#ManyToMany(cascade = CascadeType.ALL)
private Set<File> files;
public Set<File> getFiles() {
return files;
}
public void setFiles(Set<File> files) {
this.files = files;
}
}
and
import java.util.Date;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#NamedQueries({ #NamedQuery(name = File.findAll, query = "SELECT f FROM File f ORDER BY f.createdOn"),
#NamedQuery(name = File.findByName, query = "SELECT f FROM File f WHERE f.name = :name") })
#NamedEntityGraphs({
#NamedEntityGraph(name = File.EG_LoadRoles, attributeNodes = { #NamedAttributeNode("roles") }),
#NamedEntityGraph(name = File.EG_LoadALL, includeAllAttributes=true)
})
#Entity
public class File extends NamedDomainObject{
/**
*
*/
private static final long serialVersionUID = 3696244073145217983L;
public static final String findByName = "File.findByName";
public static final String findAll = "File.findAll";
public static final String EG_LoadRoles = "File.EG_LoadRoles";
public static final String EG_LoadALL = "File.EG_LoadALL";
#ManyToMany
private Set<Role> roles;
#ManyToMany
private Set<FileCategory> fileCategories;
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Set<FileCategory> getFileCategories() {
return fileCategories;
}
public void setFileCategories(Set<FileCategory> fileCategories) {
this.fileCategories = fileCategories;
}
}
and the class Kunde in my war
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import de.xxx.common.domain.Address;
import de.xxx.common.domain.NamedDomainObjectWithFiles;
#NamedQueries({ #NamedQuery(name = Kunde.findAll, query = "SELECT b FROM Kunde b where b.activ=1 ORDER BY b.name"),
#NamedQuery(name = Kunde.findByName, query = "SELECT b FROM Kunde b WHERE b.name = :name") })
#NamedEntityGraphs({
#NamedEntityGraph(name = Kunde.EG_loadAll,
attributeNodes = {
#NamedAttributeNode(value = "files", subgraph = Kunde.SG_filesLoadAll)
},
subgraphs = {
#NamedSubgraph(name = Kunde.SG_filesLoadAll,
attributeNodes = {
#NamedAttributeNode("roles"),
#NamedAttributeNode("fileCategories")
}
)
}
)
})
#Entity
public class Kunde extends NamedDomainObjectWithFiles {
/**
*
*/
private static final long serialVersionUID = -7339308550470317787L;
public static final String findByName = "Kunde.findByName";
public static final String findAll = "Kunde.findAll";
public static final String EG_loadAll = "Kunde.EG_loadAll";
public static final String SG_filesLoadAll = "Kunde.SG_filesLoadAll";
#OneToMany(cascade = CascadeType.ALL, mappedBy = "kunde", orphanRemoval = true)
private List<Objekt> objekte;
public Kunde() {
}
public List<Objekt> getObjekte() {
return objekte;
}
public void setObjekte(List<Objekt> objekte) {
this.objekte = objekte;
}
}
Everything works fine until i try to activate the subgraph 'Kunde.SG_filesLoadAll' in my class Kunde. During startup i get following exception:
org.hibernate.MappingException: Unknown entity: de.xxx.common.domain.NamedDomainObjectWithFiles
If i only set
#NamedEntityGraph(name = Kunde.EG_loadAll,
attributeNodes = {
#NamedAttributeNode(value = "files")
}
no exception is thrown during startup.
I hope you can help me.
I tested this code with the same result on wildfly 8.1 and 9.0.1.
Michael
#Edit:
Here is my persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/ObjektmanagementDS</jta-data-source>
<jar-file>lib/common-0.0.1.jar</jar-file>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/objektmanagement?UseUnicode=true&characterEncoding=utf8" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
Related
I am attempting to write a rest API to interface with a MariaDB. I feel like I am most of the way there however I am recieving the following error:
java.lang.IllegalArgumentException: Unknown entity: Models.User
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:808)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at test.Application.addUser(Application.java:40)
at test.Application.main(Application.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:542)
at java.base/java.lang.Thread.run(Thread.java:834)
I imagine that this is because I have incorrectly configured the user class in the persistence.xml file in resources/META-INF. Below are the relavent inter relating files:
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="potholeAPI" transaction-
type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>Models.User</class>
<properties>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost:3306/PotholeDB?
useUnicode=true&useJDBCCompliantTimezoneShift
=true&useLegacyDate
timeCode=false&serverTimezone=UTC"/>
<property name="javax.persistence.jdbc.user" value="admin"/>
<property name="javax.persistence.jdbc.password" value="admin"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
</properties>
</persistence-unit>
User.java
package Models;
import org.hibernate.annotations.Entity;
import org.hibernate.annotations.Table;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
#Table(appliesTo = "Users")
public class User implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id", unique = true)
private int id;
#Column(name = "name", unique = true)
private String name;
#Column(name = "created_date")
private int created_date;
getters and setters....
and the main and driver for my testing
Application.java
package test;
import Models.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
#SpringBootApplication
public class Application {
private static EntityManagerFactory ENTITY_MANAGER_FACTORY =
Persistence.createEntityManagerFactory("potholeAPI");
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
addUser(1, "jim");
addUser(2, "bob");
getUser(1);
getUsers();
ENTITY_MANAGER_FACTORY.close();
}
public static void addUser(int id, String name) {
EntityManager em = ENTITY_MANAGER_FACTORY.createEntityManager();
EntityTransaction et = null;
Date date = new Date();
try {
et = em.getTransaction();
et.begin();
User user = new User();
user.setId(id);
user.setName(name);
user.setCreated_date(date.getDate());
em.persist(user);
} catch (Exception ex) {
if (et != null) {
et.rollback();
}
ex.printStackTrace();
} finally {
em.close();
}
}
public static void getUser(int id) {
EntityManager em = ENTITY_MANAGER_FACTORY.createEntityManager();
String query = "SELECT u FROM User u WHERE u.id = :userID";
TypedQuery<User> tq = em.createQuery(query, User.class);
tq.setParameter("userID", id);
User user = null;
try {
user = tq.getSingleResult();
System.out.println(user.getName() + " ");
} catch (NoResultException e) {
System.out.println("ex");
e.printStackTrace();
} finally {
em.close();
}
}
public static void getUsers() {
EntityManager em = ENTITY_MANAGER_FACTORY.createEntityManager();
String query = "SELECT u FROM User u WHERE u.id IS NOT NULL";
TypedQuery<User> tq = em.createQuery(query, User.class);
List<User> users;
try {
users = tq.getResultList();
users.forEach(user-> System.out.println(user.getName()+ " "));
} catch (NoResultException e) {
System.out.println("ex");
e.printStackTrace();
} finally {
em.close();
}
}
}
My suspicion is that I screwed up the xml file however I am new to spinning up an API like this so I am not fully confident.
Tablename is 'User',so User.java->#Table(appliesTo = "Users") should be #Table(appliesTo = "User")
I am learning manytomany relationship in hibernate from the tutorial. My example project has two tables called product_table and order_table. I was using many to many relationship between these two tables.
While executing my code I found the following error in the console:
Exception in thread "main" org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table: product_details, for columns: [org.hibernate.mapping.Column(orders)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:456)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:423)
at org.hibernate.mapping.Property.isValid(Property.java:226)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597)
at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:459)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
at com.hibernatetest.main.MainApp.hibernateSession(MainApp.java:98)
at com.hibernatetest.main.MainApp.main(MainApp.java:93)
Here's my Hibernate configuration file:
<!-- ~ Hibernate, Relational Persistence for Idiomatic Java ~ ~ License:
GNU Lesser General Public License (LGPL), version 2.1 or later. ~ See the
lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- In case of using MySQL greater than 5 use MYSQL5 Dialect in stead of mysqldialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- Assume test is the database name -->
<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_test?createDatabaseIfNotExist=true</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="com.hibernatetest.dto.ProductDetails" />
<mapping class="com.hibernatetest.dto.OrderDetails" />
</session-factory>
</hibernate-configuration>
Here's my OrderDetails classes:
package com.hibernatetest.dto;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity
#Table(name = "product_details")
public class ProductDetails {
private int productId;
private String productName;
#ManyToMany(mappedBy="product_details")
private Collection<OrderDetails> orders=new ArrayList();
public ProductDetails() {
}
public ProductDetails(String productName) {
this.productName = productName;
}
#Id
#Column(name = "product_id")
#GeneratedValue(strategy = GenerationType.AUTO)
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
#Column(name = "product_name")
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Collection<OrderDetails> getOrders() {
return orders;
}
public void setOrders(Collection<OrderDetails> orders) {
this.orders = orders;
}
}
Here is my OrderDetails class:
package com.hibernatetest.dto;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "order_details")
public class OrderDetails {
private int orderId;
private String orderName;
#ManyToMany
private Collection<ProductDetails> products = new ArrayList();
public OrderDetails() {
super();
}
public OrderDetails(String orderName) {
super();
this.orderName = orderName;
}
#Id
#Column(name = "order_id")
#GeneratedValue(strategy = GenerationType.AUTO)
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
#Column(name = "order_name")
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public Collection<ProductDetails> getProduct() {
return products;
}
public void setProduct(Collection<ProductDetails> products) {
this.products = products;
}
}
Here is MainApp class:
package com.hibernatetest.main;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.hibernatetest.dto.Address;
import com.hibernatetest.dto.Office;
import com.hibernatetest.dto.OrderDetails;
import com.hibernatetest.dto.ProductDetails;
import com.hibernatetest.dto.UserDetails;
public class MainApp {
public static void main(String[] args) {
/*
* UserDetails user = new UserDetails(); UserDetails user2=new UserDetails();
* Address address1=new Address("test street1", "test city1", "test state",
* "0000"); Address address2=new Address("test street2", "test city2",
* "test state", "0001"); //user.setUserId(2); user.setUsername("Test User 1");
* user2.setUsername("Test User 2"); user.setJoinedDate(new Date());
* user2.setJoinedDate(new Date()); user.setHomeAddress(address1);
* user.setOfficeAddress(address2); user2.setHomeAddress(address2);
* user2.setOfficeAddress(address1); user.setDescription("test data 1");
* user2.setDescription("test data 2"); user.setJoinedTime(new Date());
* user2.setJoinedTime(new Date());
*
* String officePhone1="00000000"; String officePhone2="00000001"; String
* officePhone3="00000002"; Collection<String> phoneNumbers=new
* ArrayList<String>(); phoneNumbers.add(officePhone1);
* phoneNumbers.add(officePhone2); phoneNumbers.add(officePhone3); Office
* office=new Office(1,"Test Office 1", address1,phoneNumbers);
*
* SessionFactory sessionFactory = new
* Configuration().configure().buildSessionFactory();
*
* Session session = sessionFactory.openSession();
*
* session.beginTransaction();
*
* session.save(user); session.save(user2); session.save(office);
*
* session.getTransaction().commit();
*
* session.close();
*
* user=null;
*
* session= sessionFactory.openSession(); session.beginTransaction();
* user=session.get(UserDetails.class,2);
*
* System.out.println(user.getUserId()+" "+user.getDescription());
*
* session.close(); office=null; session=sessionFactory.openSession();
* session.beginTransaction(); office=session.get(Office.class, 1);
* System.out.println(office.getOfficeName()); session.close();
* System.out.println(office.getPhoneList().size());
*/
ProductDetails product1 = new ProductDetails("Sample product 1");
ProductDetails product2 = new ProductDetails("Sample product 2");
ProductDetails product3 = new ProductDetails("Sample product 3");
ProductDetails product4 = new ProductDetails("Sample product 4");
OrderDetails order1 = new OrderDetails("Order No 1");
OrderDetails order2 = new OrderDetails("Order No 2");
product1.getOrders().add(order1);
product1.getOrders().add(order2);
product2.getOrders().add(order2);
order1.getProduct().add(product1);
order1.getProduct().add(product2);
order1.getProduct().add(product3);
order2.getProduct().add(product1);
order2.getProduct().add(product3);
order2.getProduct().add(product4);
List<Object> insetableObjects = new ArrayList<Object>();
insetableObjects.add(product1);
insetableObjects.add(product2);
insetableObjects.add(product3);
insetableObjects.add(product4);
insetableObjects.add(order1);
insetableObjects.add(order2);
hibernateSession(insetableObjects);
}
public static void hibernateSession(List<Object> collection) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
for (Object obj : collection) {
session.save(obj);
System.out.println("Object Added");
}
session.getTransaction().commit();
session.close();
}
}
Please guide me to the next steps and thanks in advance.
See this tutorial and Jack Flamp's comments. In order to establish a ManyToMany relationship, you need a #JoinTable referencing the table you want to use in its specific class, and a reference in the other. For instance, in your case it would be something like:
ProductDetails:
#Entity
#Table(name = "product_details")
public class ProductDetails {
private int productId;
private String productName;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(
name = "order_product",
joinColumns = { #JoinColumn(name = "productId") },
inverseJoinColumns = { #JoinColumn(name = "orderId") }
)
private Collection<OrderDetails> orders = new ArrayList();
[...]
OrderDetails:
#Entity
#Table(name = "order_details")
public class OrderDetails {
private int orderId;
private String orderName;
#ManyToMany(mappedBy = "orders")
private Collection<ProductDetails> products = new ArrayList();
Here, your "owning side" (= the one holding the information) is the product. Your product can have multiple orders, and an order belongs to multiple products. Of course, feel free to revert them as you wish if it does not suit your needs. The link I gave you explains well what each annotation does.
EDIT: Make sure that (in the example) the order_product table actually exists. Otherwise, it won't work.
Queries in the form of an entity class A in the form of
SELECT a from A a WHERE TYPE(a) = A
fail with
could not resolve property: class of: de.richtercloud.type.operator.nonsense.A [SELECT a from de.richtercloud.type.operator.nonsense.A a WHERE TYPE(a) = A]
which I don't understand because restricting A to A should exclude all superclass instances which aren't As as well as subclass instances.
Example:
package de.richtercloud.type.operator.nonsense;
import java.io.File;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
/**
* Illustrates the problem/misunderstanding that storing an {#link A} and
* querying it with a {#code WHERE TYPE([identifier]) = A} fails with
* {#code org.hibernate.QueryException: could not resolve property:
* class of: de.richtercloud.type.operator.nonsense.A}.
* #author richter
*/
public class NewMain {
private final static File DATABASE_DIR = new File("/tmp/type-operator-nonsense");
private final static String DERBY_CONNECTION_URL = String.format("jdbc:derby:%s", DATABASE_DIR.getAbsolutePath());
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
//setup database
EntityManagerFactory entityManagerFactory = null;
try {
Map<Object, Object> entityManagerFactoryMap = new HashMap<>();
entityManagerFactoryMap.put("javax.persistence.jdbc.url",
String.format("%s;create=%s", DERBY_CONNECTION_URL, !DATABASE_DIR.exists()));
entityManagerFactory = Persistence.createEntityManagerFactory("type-operator-nonsense",
entityManagerFactoryMap);
//show issue
EntityManager entityManager = entityManagerFactory.createEntityManager();
A a = new A(1L, "b");
entityManager.getTransaction().begin();
entityManager.persist(a);
entityManager.flush();
Query query = entityManager.createQuery("SELECT a from A a WHERE TYPE(a) = A");
List<?> queryResult = query.getResultList();
entityManager.getTransaction().commit();
System.out.println(queryResult.size());
}finally {
if(entityManagerFactory != null) {
entityManagerFactory.close();
}
}
}
}
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="type-operator-nonsense" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>de.richtercloud.type.operator.nonsense.A</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:/tmp/type-operator-nonsense"/>
<property name="javax.persistence.jdbc.user" value=""/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
with org.hibernate:hibernate-entitymanager:5.1.0.Final and org.apache.derby:derby:10.11.1.1
A is a POJO in this example which doesn't involve inheritance, that shouldn't matter for the restriction I expect (although it wouldn't make sense to apply it if there's no inheritance):
package de.richtercloud.type.operator.nonsense;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class A implements Serializable {
private static final long serialVersionUID = 1L;
private String b;
#Id
private Long id;
public A() {
}
public A(Long id, String b) {
this.id = id;
this.b = b;
}
public void setB(String b) {
this.b = b;
}
public String getB() {
return b;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
This behaviour occurs due to a hibernate bug https://hibernate.atlassian.net/browse/HHH-10653. The example above works fine with OpenJPA.
TYPE() can only be used in inheritance mapping.
Is A a class in a inheritance mapping and A either the route class with #Inheritance or A extends a class that has #Inheritance declared?
Example.
#Inheritance
#Entity
public class Project
#Entity
public class DesignProject extends Project
#Entity
public class QualityProject extends Project
#Entity
public class SoftwareProject extends Project
Now you can use TYPE()
SELECT p
FROM Project p
WHERE TYPE(p) = DesignProject OR TYPE(p) = QualityProject
I have listed my class in persistence.xml but mapped class is not recognized inside.
I tried <exclude-unlisted-classes>false</exclude-unlisted-classes>
But no luck.
My persistence.xml file
<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="advertiserAPI" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.advertiser.model.Application</class>
<properties>
<property name="hibernate.connection.url" value="jdbc:mysql://host:port/DB" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.autoReconnect" value="true"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="password"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.validator.apply_to_ddl" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.use_sql_comments" value="true"/>
<property name="hibernate.default_batch_fetch_size" value="16"/>
<property name="hibernate.current_session_context_class" value="thread"/>
</properties>
</persistence-unit>
</persistence>
Test class file
package com.advertiser.model.test;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.servlet.ServletException;
import org.junit.Test;
import com.advertiser.model.Application;
public class ApplicationTest {
#Test
public void listAll() throws ServletException {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("advertiserAPI");
try {
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT id FROM Application");
System.out.println("query " + query);
} catch (Exception ex) {
ex.printStacktrace();
}
}
}
Application class has following
package com.advertiser.model;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Entity;
import static org.apache.commons.lang.builder.ToStringStyle.MULTI_LINE_STYLE;
#Entity
#Table(name = "applications")
public class Application {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false)
private Integer id;
#Column(name = "name", length = 255)
private String name;
#Column(name = "host", length = 255, nullable = false)
private String host;
#Column(name = "app_type", columnDefinition = "TINYINT")
private String appType;
#ManyToOne
#JoinColumn(name = "advertiser_id")
private Integer advertiserId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getAppType() {
return appType;
}
public void setAppType(String appType) {
this.appType = appType;
}
public Integer getAdvertiserId() {
return advertiserId;
}
public void setAdvertiserId(Integer advertiserId) {
this.advertiserId = advertiserId;
}
}
You have annotated your class with #org.hibernate.annotations.Entity instead of annotating it with #javax.persistence.Entity.
here's is the problem
I have a java class Agence that has a #ManytoOne relationship with my class Reseau .
there is my Agence code :
package ma.kafil.bank;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
public class Agence implements Serializable{
private int idAgence;
private String labelle;
private Reseau reseau;
public Agence(String labelle) {
this.labelle = labelle;
}
public Agence() {
}
#ManyToOne
public Reseau getReseau() {
return reseau;
}
public void setReseau(Reseau reseau) {
this.reseau = reseau;
}
#Id
#GeneratedValue
public int getIdAgence() {
return idAgence;
}
public void setIdAgence(int idAgence) {
this.idAgence = idAgence;
}
public String getLabelle() {
return labelle;
}
public void setLabelle(String labelle) {
this.labelle = labelle;
}
}
and my Reseau Class :
package ma.kafil.bank;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class Reseau implements Serializable{
private int idReseau;
private String Libelle;
private ArrayList<Agence> Agences = new ArrayList();
//Constructor without arguments
public Reseau() {
}
public Reseau(String Libelle) {
this.Libelle = Libelle;
}
public void ajouterAgence(Agence a){
Agences.add(a);
}
#Id
#GeneratedValue
public int getIdReseau() {
return idReseau;
}
public void setIdReseau(int idReseau) {
this.idReseau = idReseau;
}
public String getLibelle() {
return Libelle;
}
public void setLibelle(String Libelle) {
this.Libelle = Libelle;
}
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}, mappedBy="reseau")
public Collection<Agence> getAgences() {
return Agences;
}
public void setAgences(ArrayList<Agence> Agences) {
this.Agences = Agences;
}
public void addAgence(Agence a){
this.Agences.add(a);
}
}
And Finally the main class :
package ma.kafil.bank;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Main {
public static void main(String [] args){
//Creating Entity Manager
//persistence-unit name="test"
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();
//beginning the transaction
em.getTransaction().begin();
//Creating a new Reseau r with r.labbelle = "Centre" and r.id=1
Reseau r = new Reseau("Centre");
r.setIdReseau(1);
//Creating a new Agence a
Agence a = new Agence("Nom Agence");
a.setIdAgence(2);
//adding a to my Reseau (What's the problem with that ?? )
r.addAgence(a);
em.persist(r);
a.setIdAgence(1990);
a.setReseau(r);
em.persist(a);
em.getTransaction().commit();
//closing em and emf
em.close();
emf.close();
}
}
Here is the stack trace :
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: ma.kafil.bank.Reseau
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:226)
at ma.kafil.bank.Main.main(Main.java:30)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: ma.kafil.bank.Reseau
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:79)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220)
... 1 more
Java Result: 1
And here is persistence.xml :
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class> ma.kafil.bank.Agence</class>
<class> ma.kafil.bank.Reseau</class>
<properties>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/awbawards"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit> </persistence>
Thanks in Advance
In your reseau class, the agences list is never initialized, it should be:
#Entity
public class Reseau implements Serializable{
private int idReseau;
private String Libelle;
private List<Agence> Agences = new ArrayList<Agence>();
Also your field, getter and setter declarations should all use the type List, not Collection not ArrayList and your field shouldn't start with a capital letter (java naming conventions):
private List<Agence> agences = new ArrayList<Agence>();
public List<Agence> getAgences() {
return agences;
}
public void setAgences(List<Agence> agences) {
this.agences = agences;
}
The problem is when you do r.addAgence(a); it is possible that list of Agences is null for few Reseau. A quick fix can be done in your add method -
public void addAgence(Agence a){
if(Agences==null){//do this check to avoid null pointer
Agences = new ArrayList<Agence>();
}
this.Agences.add(a);
}
Since you edited your question I'll post it as an answer.
Based on this reply https://stackoverflow.com/a/2442036/1094430 you should not set your ID by code if you DB is set to auto generate them.
So remove
r.setIdReseau(1);
...
a.setIdAgence(2);
...
a.setIdAgence(1990);
from your code and then do the persist.
Try with this main:
package ma.kafil.bank;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Main {
public static void main(String [] args){
//Creating Entity Manager
//persistence-unit name="test"
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();
//beginning the transaction
em.getTransaction().begin();
//Creating a new Reseau r with r.labbelle = "Centre" and r.id=1
Reseau r = new Reseau("Centre");
r.setIdReseau(1);
//Creating a new Agence a
Agence a = new Agence("Nom Agence");
a.setIdAgence(2);
a.setIdAgence(1990);
a.setReseau(r);
//adding a to my Reseau (What's the problem with that ?? )
r.addAgence(a);
em.persist(r);
em.getTransaction().commit();
//closing em and emf
em.close();
emf.close();
}
}
It should work, because both objects are linked.