I use :
mysql-connector-java 6.0.6
hibernate 5.2.10.Final
spring 4.3.8.RELEASE
Class code :
public class PhoneNumber extends AbstractValue{
public static final int CELL_PHONE = 1, HOME_PHONE = 2, WORK_PHONE = 3;
public PhoneNumber(String value, Integer type) {
super(value, type);
}
public PhoneNumber() {
this(null,null);
}
}
Parent class :
public abstract class AbstractValue {
private String value;
private Integer type;
public AbstractValue(String value, Integer type) {
this.value = value;
this.type = type;
}
public String getValue() {
return value;
}
public Integer getType() {
return type;
}
public void setValue(String value) {
this.value = value;
}
public void setType(Integer type) {
this.type = type;
}
}
Mapping :
<entity class="PhoneNumber" name="PhoneNumber">
<table name="PhoneNumber"/>
<attributes>
<id name="value">
</id>
<basic name="type">
<column nullable="false"/>
</basic>
</attributes>
</entity>
Already tried :
<entity class="PhoneNumber" name="PhoneNumber">
<table name="PhoneNumber"/>
<attributes>
<id name="value" access="FIELD">
<generated-value strategy="SEQUENCE" generator="IdSeq" />
<sequence-generator name="IdSeq" sequence-name="IdSeq" allocation-size="1" />
</id>
<basic name="type">
<column nullable="false"/>
</basic>
</attributes>
</entity>
<entity class="PhoneNumber" name="PhoneNumber">
<table name="PhoneNumber"/>
<attributes>
<id name="value">
<generated-value strategy="IDENTITY" generator="uuid" />
</id>
<basic name="type">
<column nullable="false"/>
</basic>
</attributes>
</entity>
<entity class="PhoneNumber" name="PhoneNumber">
<table name="PhoneNumber"/>
<attributes>
<id name="value">
<generated-value strategy="TABLE" generator="uuid" />
<table-generator name="uuid" />
</id>
<basic name="type">
<column nullable="false"/>
</basic>
</attributes>
</entity>
And already read : (so i hope i don't do duplicate)
org.hibernate.AnnotationException: No identifier specified for entity: com.ubosque.modelo.Ciudadano
org.hibernate.AnnotationException: No identifier specified for entity: login.Users
java.lang.RuntimeException: org.hibernate.AnnotationException: No identifier specified for entity
Org.Hibernate.AnnotationException: No Identifier Specified For Entity I don't have a id in my table
org.hibernate.AnnotationException: No identifier specified for entity using JPA XML entity-mapping
No Identifier specified exception even when it was
string id generator
How to use #Id with String Type in JPA / Hibernate?
and some more...
error :
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.mayan.nst.server.model.PhoneNumber
IF its possible i was prefer a solution were the id will NOT be generated
Thanks you very mutch for read, and for any help
Thanks to Neil Stocktin the problem was that i tried to get superclass property from this child. (not working). solution will be add
<entity class="AbstractValue">
<attributes>
<id name="value">
</id>
</attributes>
</entity>
and remove the from the child
Update
better solution, to separate the super class childrens tables. use :
<mapped-superclass class="AbstractValue">
<attributes>
<id name="value"/>
<basic name="type">
<column nullable="false"/>
</basic>
</attributes>
</mapped-superclass>
Related
I am trying to save to two tables in SQL server using Hibernate:
ORDER and ORDER_ITEM
I get an error:
Attribute "type" must be declared for element type "column".
Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Unable to read XML.
This produces a NullPointerException
If I understand correctly, this means that when I try to save to the order_item table, the getter for the foreign key is empty, but how would I set it if is designed to 'Autoincrement', I thought that hibernate would handle this in it's transaction.
Below are my POJO's and Hibernate mappings. I have omitted the getters and setters from this copy/paste, but they are present in my actual code
I am also successful in saving just to the ORDER table if I remove the set
Order.java:
public class Order {
public Order(){
super();
}
private int orderId;
private Set<LineItem> items;
private String strPhone;
private String strEmail;
private String strFirstName;
private String strLastName;
private String strParentFirstName;
private String strParentLastName;
private String strOrganizationName;
private String strOrganizationType;
private String strComment;
}
order.hbm.xml:
<hibernate-mapping>
<class name="dbobjects.Order" table="orders">
<id name="orderId" type="integer" column="order_id">
<generator class="increment"/>
</id>
<property name="strPhone" type="string" column="phone_number"/>
<property name="strFirstName" type="string" column="first_name"/>
<property name="strLastName" type="string" column="last_name"/>
<property name="strParentFirstName" type="string" column="parent_first_name"/>
<property name="strParentLastName" type="string" column="parent_last_name"/>
<property name="strOrganizationName" type="string" column="organization_name"/>
<property name="strOrganizationType" type="string" column="organization_type"/>
<property name="strComment" type="string" column="comments"/>
<set name="items" table="order_item" fetch="select" cascade="all">
<key>
<column name="orderId" type="java.lang.Integer"/>
</key>
<one-to-many class="dbobjects.LineItem"/>
</set>
</class>
LineItem.java:
public class LineItem {
public LineItem(){
super();
}
private int orderItemId;//this will be the primary key
private int orderId;//this is the foreign key to the order
private String age;
private String gender;
private String type;
private String itemSize;
private int itemQuantity;
}
lineItem.hbm.xml:
<id column="order_item_id" name="orderItemId" type="integer">
<generator class="increment"/>
</id>
<property column="age" name="age" type="string"/>
<property column="gender" name="gender" type="string"/>
<property column="quantity" name="itemQuantity" type="integer"/>
<property column="size" name="itemSize" type="string"/>
<property column="clothing_type" name="clothingType" type="string"/>
<many-to-one name="orderId" class="dbobjects.Order" fetch="select" column="order_id" type="java.lang.Integer"/>
This is where the error is thrown when I Instanciate the session:
**session = HibernateUtil.getSessionFactory().openSession();**←
try{
session.beginTransaction();
session.save(order);
session.getTransaction().commit();
So the question is: How do I handle this situation with 'autoincrement' primary key that is not accessible to another table as a foreign key
So, There were a few problems:
In order to submit a 'child' to the database, I needed to show who is the parent.
This means that my LineItem Class needed a
Order order;
property instead of a simple
private String orderID;
this was accomplished after the Order object was ready to be submitted to the DB but before the actual call:
for (LineItem item : order.getItems()) {
item.setOrder(order);
}
I also changed my DTD's from !DOCTYPE hibernate-configuration SYSTEM classpath://org/hibernate/hibernate-mapping-3.0.dtd"
to
!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"
Just add "type" attribute like this :
<column name="orderId" type="java.lang.Integer"/>
Try to replace :
<many-to-one name="orderId" column="order_id" class="dbobjects.Order" cascade="all">
<column name="orderId" type="java.lang.Integer"/>
</many-to-one>
by
<many-to-one name="orderId" column="order_id" class="dbobjects.Order" cascade="all"/>
I have a node db with five pieces of data:
id(int, PK)
question(varchar)
result(varchar)
left_id(int, FK)
right_id(int, FK)
and two foreign keys in the same table
left_id -> id
right_id -> id
here is my bean
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name="id")
#NotNull
private int id;
#Column (name = "question")
private String question;
#Column ( name = "result")
private String result;
#OneToOne(fetch= FetchType.LAZY)
#JoinColumn(name="left_id", referencedColumnName="id", insertable=true, updatable=true)
private Nodes left;
#OneToOne(fetch= FetchType.LAZY)
#JoinColumn(name="right_id", referencedColumnName="id", table="node", insertable=true, updatable=true)
private Nodes right;
and here is my dao
public void insert_question(String question, int left) throws HibernateException
{
try
{
Session session = getSession();
Transaction tx = session.beginTransaction();
Nodes node = new Nodes();
Nodes leftNode = new Nodes();
//insert question
node.setQuestion(question);
// insert left_id with fk
leftNode.setId_node(left);
node.setLeftNodes(leftNode);
session.saveOrUpdate(node);
tx.commit();
session.close();
}
catch (HibernateException e)
{
e.printStackTrace();
}
}
I have a same insert method for result but without foreign key.
My new question and new result are insert my db but not my left_id.
In Eclipse, hibernate tell me
Infos: Hibernate: select nodes_.id, nodes_.question as question0_, nodes_.result as result0_ from node nodes_ where nodes_.id=?
Infos: Hibernate: insert into node (question, result, id) values (?, ?, ?)
Infos: Hibernate: insert into node (question, result, id) values (?, ?, ?)
When hibernate insert a new data, why there are no left/right_id ?
thanks
EDIT:
I changed my hbm. Before it was like that
<hibernate-mapping>
<class name="com.beans.Nodes" table="node">
<id name="id" type="int" access="field">
<column name="id" />
<generator class="assigned" />
</id>
<property name="question" type="java.lang.String">
<column name="question" />
</property>
<property name="result" type="java.lang.String">
<column name="result" />
</property>
<one-to-one name="left" class="com.beans.Nodes" access="field"></one-to-one>
<one-to-one name="right" class="com.beans.Nodes" access="field"></one-to-one>
</class>
</hibernate-mapping>
and now it's like that
<hibernate-mapping>
<class name="com.beans.Nodes" table="node">
<id name="id" type="int" access="field">
<column name="id" />
<generator class="assigned" />
</id>
<property name="question" type="java.lang.String">
<column name="question" not-null="false"/>
</property>
<property name="result" type="java.lang.String">
<column name="result" not-null="false"/>
</property>
<many-to-one name="Left"
column="left_id"
unique="true"
not-null="false"
/>
<many-to-one name="Right"
column="right_id"
unique="true"
not-null="false"
/>
</class>
</hibernate-mapping>
and it's works !
I have the following classes:
Guide class:
public abstract class Guide
{
private Long idGuide;
private String name;
private GuideContainer parent;
/** GETTERS & SETTERS*/
}
GuideContainer:
public class GuideContainer extends Guide
{
private Guide children;
/** GETTER & SETTERS */
}
GuideFile:
public class GuideFile extends Guide
{
private String uri;
/**GETTERS & SETTERS */
}
with the following mappings:
For Guide:
<hibernate-mapping>
<class name="Guide" table="guides" abstract="true">
<id name="idGuide" type="integer" column="idGuide">
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String" column="name" />
<discriminator column="type" type="java.lang.String" />
<many-to-one class="GuideContainer" fetch="join" name="parent">
<column name="parent" />
</many-to-one>
</class>
</hibernate-mapping>
GuideFile:
<hibernate-mapping>
<subclass extends="Guide" name="GuideFile" discriminator-value="file">
<property name="uri" type="java.lang.String" column="uri" />
</subclass>
</hibernate-mapping>
GuideContainer:
<hibernate-mapping>
<subclass extends="Guide" name="GuideContainer" discriminator-value="container">
<set fetch="select" inverse="true" lazy="true" name="children" sort="unsorted" table="children">
<key>
<column name="parent" not-null="false" />
</key>
<one-to-many class="Guide" />
</set>
</subclass>
</hibernate-mapping>
When I try to get all the guides with a given parent
Query query = getSession().createQuery("from Guide g where parent = :parent order by type").setParameter("parent", parent);
List<Guide> guides= query.list();
return guides;
I am getting the following exception:
IllegalArgumentException occurred calling getter of Guide.idGuide
And after that:
java.lang.IllegalArgumentException: object is not an instance of declaring class
What am I doing wrong?
Solved. Query should have been:
from Guide g where parent.idGuide = :parent order by type
I want to save an object to my sub-class ArticleZoning whose super class Zoning contain a List of Class zoneData which also contain a class ZoneCoordinate. When I save the object of my sub-class ArticleZoning it gives an exception.
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.qait.cdl.eon.commons.domain.ZoneData._com.qait.cdl.eon.commons.domain.Zonning.zoneDatasBackref
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210).....
Here is *Zonning hbm*Mapping file:-
<class name="Zonning" table="zoning">
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<list name="zoneDatas" lazy="false" cascade="all-delete-orphan" >
<key column="zoning_id" not-null="true"/>
<list-index column="idx" base="1" />
<one-to-many class="com.qait.cdl.eon.commons.domain.ZoneData" />
</list>
<many-to-one class="com.qait.cdl.eon.commons.domain.MagazineIssue" unique="true" column="issue_id" name="issue"/>
<property name="pageNumber" column="article_on_pageNumber" type="string" not-null="true" />
<joined-subclass name="ArticleZoning" extends="Zonning" table="article_zoning">
<key column="article_id"/>
<property name="articleTitle" column="article_title" type="string" not-null="true" />
<property name="articleOrder" column="article_order" type="int" not-null="true" />
<property name="articleFileId" column="article_file_id" type="string" not-null="true" />
<property name="articleType" column="article_type">
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.qait.cdl.eon.common.constants.ArticleType</param>
</type>
</property>
<property name="articleSubTitle" column="article_sub_title" type="string" not-null="true" />
<property name="articleGenre" column="article_genre">
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.qait.cdl.eon.common.constants.Genre</param>
</type>
</property>
</joined-subclass>
<joined-subclass name="AdvertisementZoning" extends="Zonning" table="advertisement_zoning">
<key column="advertisement_id" />
<property name="adVendor" column="ad_vendor" type="string" not-null="true" />
<property name="vendorUrl" column="vendor_url" type="string" not-null="true" />
<property name="adProduct" column="ad_product" type="string" not-null="true" />
<list name="adKeywords" table="ad_keywords" lazy="false" cascade="all">
<key column="ad_keywords_id" />
<list-index base="0" column="idx"/>
<element column="keywords" type="string" />
</list>
</joined-subclass>
</class>
Here is ZoneData Hbm
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<property name = "zoneOrder" column = "zone_order" type = "int" not-null="true"/>
<property name = "zoneFileId" column = "zone_file_id" type = "string" not-null="true"/>
<property name = "zoneShape" column = "zone_shape" type = "string" not-null="true" access="field"></property>
<many-to-one name="coordinates" column="coordinates_id" lazy="false" class="com.qait.cdl.eon.commons.domain.ZoneCoordinates"
unique="true" not-null="true" cascade="all-delete-orphan"/>
</class>
Here is ZoneCoordinate hbm
<class name="ZoneCoordinates" table="zone_coordinates">
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<property name = "leftTopX" column = "left_top_x" type = "float" not-null="true" />
<property name = "leftTopY" column = "left_top_y" type = "float" not-null="true" />
<property name = "rightBottomX" column = "right_bottom_x" type = "float" not-null="true" />
<property name = "rightBottomY" column = "right_bottom_y" type = "float" not-null="true" />
</class>
Here is Zoning pojo
class Zoning{
private List<ZoneData> zoneDatas =new ArrayList<>();
private MagazineIssue issue;
private String pageNumber;
//getter and setter
}
Here is ZoneData POJO
class ZoneData{
private int zoneOrder;
private String zoneFileId ;
private ZoneCoordinates coordinates;
private final String zoneShape = "RECT";
//getter and setter
}
Here is ArticleZoning POJO
class ArticleZoning extends Zoning{
private String articleTitle;
private String articleOrder;
private ArticleType articleType;
private String articleFileId;
private String articleSubTitle;
private Genre articleGenre;
//getter and setter
}
Here is ZoneCoordinate POJO
class ZoneCoordinate{
private float leftTopX;
private float leftTopY;
private float rightBottomX;
private float rightBottomY;
//getter and setter
}
First, ArticleZoning POJO has articleOrder as String type. Your Zonning.hbm says articleOrder is of int type.
Secondly, as zoning table is unable to save, hence its foreign key is null.
I was wondering if it's possible in JPA to define a generic entity like in my case PropertyBase and derive concrete entity classes like ShortProperty and StringProperty and use them with the SINGLE_TABLE inheritance mode?
If I try to commit newly created ElementModel instances (see ElementModelTest) over the EntityManager I always get an NumberFormatException that "value" can't be properly converted to a Short. Strangely enough if I define all classes below as inner static classes of my test case class "ElementModelTest" this seems to work.
Any ideas what I need to change to make this work?
I'm using EclipseLink eclipselink-2.6.0.v20131019-ef98e5d.
public abstract class PersistableObject implements Serializable {
private String id = UUID.randomUUID().toString();
private Long version;
}
public abstract class PropertyBase<T> extends PersistableObject {
private String name;
private T value;
}
public class ShortProperty extends PropertyBase<Short> {
...
}
public class StringProperty extends PropertyBase<String> {
...
}
public class ElementModel extends PersistableObject {
private StringProperty name = new StringProperty();
private ShortProperty number = new ShortProperty();
}
public class ElementModelTest extends ModelTest<ElementModel> {
#Test
#SuppressWarnings("unchecked")
public void testSQLPersistence() {
final String PERSISTENCE_UNIT_NAME = getClass().getPackage().getName();
new File("res/db/test/" + PERSISTENCE_UNIT_NAME + ".sqlite").delete();
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
for (int i = 0; i < 10; ++i) {
ElementModel device = new ElementModel();
device.setName("ElementModel: " + i);
device.setNumber((short) i);
em.persist(device);
}
em.getTransaction().commit();
em.close();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
<mapped-superclass
class="PersistableObject">
<attributes>
<id name="id">
<column name="id" />
</id>
<version name="version" access="PROPERTY">
<column name="version" />
</version>
</attributes>
</mapped-superclass>
<entity class="PropertyBase">
<table name="PropertyBase" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<basic name="name">
<column name="name" />
</basic>
<basic name="value">
<column name="value" />
</basic>
</attributes>
</entity>
<entity class="StringProperty">
<discriminator-value>StringProperty</discriminator-value>
</entity>
<entity class="ShortProperty">
<discriminator-value>ShortProperty</discriminator-value>
</entity>
<entity class="ElementModel">
<table name="ElementModel" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<one-to-one name="name">
<join-column name="name" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
<one-to-one name="number">
<join-column name="number" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
</attributes>
</entity>
</entity-mappings>
Your problem is that PropertyBase<T> is an entity with field value being persistable. Your database needs to map that field type to a column type, and you have three entities that have different java types for the same field: PropertyBase<T> is generic and has itself no idea what type its value field is, StringProperty says it is a String and ShortProperty says that is a Short. So that is a conflict.
In order to overcome this problem, you make field value transient, and for every subtype of PropertyBase<T> (like StringProperty) you can define a new persitable property with different names, eg.
StringProperty will have a private String stringValue, ShortProperty will have a private Short shortValue, and every field will be mapped to different DB column.
PS: I cannot explain why it works when you make all the classes static inner.