annotated hibernate mapping id/long foreign key to nullable column - java

I've got the following class mapping a MySQL table:
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "parent_id")
private long parentId;
and I get the following error when dealing with columns that have NULL value of parent_id column:
INFO: HHH000327: Error performing load command : org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.blogspot.symfonyworld.wealthylaughingduck.model.Category.parentId
This is just a java error: NULL can't be assigned to long type (private long parentId). I couldn't find any hint how to overcome this problem and I can only think of replacing long with Long. Is it a good idea or maybe there is some built-in hibernate annotation or whatever mechanism to do this particular stuff?

You defined your class attribute as a primitive (long), but your database table contains null values for the corresponding column. The provider (Hibernate) does not map null's to primitive because the mapping is ambiguous.
In cases where your data may contain nulls you need to use the wrapper class equivalent (in this case, Long).
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "parent_id")
private Long parentId;
}

If parentId is nullable and you need to map it as a field, you'll need to use the wrapper class.
But if (as I suspect from the filed name) you're mapping foreign keys explicitly as fields, you're likely missing out on some of an ORM's real strength in mapping associations.

Related

idMoneda property not updated in DB with #Transient directive

I have this entity, in which I have made a PUT and POST method, which do not give an error but nevertheless the idMoneda, which is a property calculated with #Transient because it is the ID of the moneda(where there is a 1 to 1 relationship with another table), it does not update me, when I look at the database it remains null even though in the POST request I put a value. I don't know if it's because the setter is wrong, or just that something else needs to be added that I don't see right now.
#Entity
#Table(name = "REMESA")
public class Remesa {
#Id
#SequenceGenerator(name = "remesa_sequence", sequenceName = "remesa_sequence", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "remesa_sequence")
#Column(name = "ID")
private Long id;
#OneToOne
#JoinColumn(name = "moneda", nullable = true)
#JsonIgnore
private Moneda moneda;
#Transient
#JsonProperty("moneda")
private Long idMoneda;
public Long getIdMoneda() {
return this.moneda.getId();
}
public void setIdMoneda(Long idMoneda) {
this.idMoneda = idMoneda;
}
}
#Transient in JPA means: do not save this field in DB. A column named "moneda_id" will automatically be generated by your relationship if it's well-defined
Java's transient keyword is used to denote that a field is not to be serialized, whereas JPA's #Transient annotation is used to indicate that a field is not to be persisted in the database, i.e. their semantics are different. Because they have different meanings.
So try to remove the transient annotation and run your code .

How to extract value from "dictionary table" in JPA

I want to map two tables (ManyToOne connection) to one object in Java. One is primary CatalogObject table, the second is just a dictionary of possible types of objects. In Java I want to just have the String of type instead of mapping to a new object.
When I want to search for all objects in the class (f.e. "database") i have to first find an Id of type "database" and then find all CatalogObjects with this Id specified. Which looks a bit tedious.
CatalogObject Table:
ID, Name, Parent_ID (FK), TYPE_ID (FK)
Type Table:
ID, Type.
I've created a mapping with CatalogObject and CatalogObjectType classes, but CatalogObjectType class holds only single String right now.
public class CatalogObject implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "parent_id")
CatalogObject parent;
String name;
#ManyToOne
#JoinColumn(name = "type_id")
CatalogObjectType type;
}
public class CatalogObjectType implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String name;
}
I want to replace CatalogObjectType with just a String value of the associated type. How to configure it for Hibernate/JPA? Can it be done?
What I want is:
public class CatalogObject implements Serializable {
...
String name;
#SomeAnnotation(name = "type_id")
String type;
}
Yes, you can map an entity to 2 database tables in 2 simple steps:
You need to annotate your entity with JPA’s #Table and #SecondaryTable annotations and provide the names of the first and second table as the value of the name parameters.
You need to annotate each attribute which you want to map to the secondary table with a #Column annotation and set the name of the secondary table as the value of the table attribute.
The #Table annotation defines the primary table to which the entity attributes get mapped by default.
The #SecondaryTable annotation specifies the second database table to which the entity gets mapped.
That’s all you need to do to map the 2 database tables to the one entity.
You can check this link for a detailed explanation with a sample.

Hibernate-OneToMany mapping for existing DB Tables

I am trying to join to Hibernate Entities in a OneToOne Mapping. I am able to fetch the data for a given primary key from the Main Entity, the joining entity, however, returns null. I am new to hibernate and any help will be appreciated.
I have two Tables,
PT_CORE
Primary Key: ptId - Integer;
Foreign Key: stId(ST_AUX) - Integer;
Columns: ptId, ptName
ST_AUX
Primary Key: stId;
Columns: stId, stName
The two tables get populated by other applications and mine is a read-only operation.
Below is my first Entity class(PtCore.java)
#Entity
#Table(name="PT_CORE")
public class PtCore implements Serializable{
#Id
#Column(name="ptId", nullable = false)
private int id;
#Column(nullable=false)
private int stId; //The Foreign key column
#OneToOne
#JoinTable( name = "core_aux", joinColumns = {#JoinColumn(Name="ptId")},
inverseJoinColumns = {#JoinColumn(Name="stId")}
)
private StAux staux;
//Getters, setters and toString() for above
}
StAux is another Entity, defined as below,
#Entity
#Table(name="ST_AUX")
public class StAux implements Serializable {
#Id
#Column(nullable=false)
private Integer stId;
#OneToOne
private PtCore ptcore;
#Column
private String stName;
//Getters, Setters and toString follow.
}
I do below in the Service method:
PtCore obj = (PtCore) session.get(PtCore.class,1);
System.out.println(obj);
In the Results, I get the value of ptName, but the stAux class variables are null, Indicating that the join does not work as expected.
First of all you have the mapping information existing in your PT_CORE. And I assume it is something like FOREIGN KEY (stid) REFERENCES (stid). If you want to use existing schema and existing data I guess there is no mapping table core_aux really existing. At least you did not mention it. However it is visible as #JoinTable annotation but still there is this above mentioned foreign key which seems to be the real mapping (so again not the join table).
I suggest the following
remove this
#Column(nullable=false)
private int stId; //The Foreign key column
from your PtCore. I think it is not needed. Also in PtCore, remove the #JoinTable (because what I told above) and add mapping informaiion to #OneToOne annotation, like:
#OneToOne
#JoinColumn(name = "stid")
private StAux staux;
from your PT_CORE.
Then in StAux alter also a bit:
#Id
#Column(name = "stid") // this might not be needed but if there is like "st_id"...
private Integer stId; // so just for sure
#OneToOne(mappedBy = "staux")
private PtCore ptcore;
Because you have existing tables and constraints there might raise errors if hibernate tries to auto-generate those again by JPA instructions.
Check this for example for more information.
UPDATE: just realized also that in your title is #OneToMany but in your code is #OneToOne.
So you might want to elaborate your question and/or title a bit.
In your relation, the owning side is PtCore, the inverse side is StAux.
In bidirectional OneToOne relations, the inverse side has to have the mappedBy attribute. Actually, the mappedBy attribute contains the name of the association-field on the owning side.
So, you must change your inverse side code (StAux Entity). You have to add mappedBy attribute to #OneToOne in StAux class:
#OneToOne(mappedBy="staux")
private PtCore ptcore;

Foreign key as primary key annotation

There is 2 entity
Product(product_id(PK),product_name..)
Store(product_id(PK,FK),product_quantity,...)
I need #OneToOne, so i do this
public class Product{
#Id
#Column(name="PRODUCT_ID")
#OneToOne(mappedBy="product")
private int product_id;
....
}
public class Store{
#Id
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "PRODUCT_ID")
private Product product;
}
Compilier says #Column(s) not allowed on a #OneToOne property: ......shopdb.entity.Product.product_id
What is the problem?
I just moved #OneToOne(mappedBy="product") to new created field in Product
private Store store;
I dont understand how it works correct;
Why i need to use 3 fields instead of 2?
You can't mark a column defined with #JoinColumn as #Id. This is applicable only to columns defined with #Column annotation.
It is also a bit strange what are you trying to do. You are basically making the produc_id primary key for both entites, so then why don't make just one?
From what I can see here, I believe that the Store should have a store id property which will be used as primary key.

Hibernate disable default behaviour

I have a problem with my Hibernate making assumptions on what to call columns.
Specifically, when I do a #ManyToOne field, where I refer to a column in the other Table.
What happens is that, If I do not enter a #JoinColumn annotation as well, it maps the field with an underscore in it's name.
For example, i have this class:
#Entity
public class User extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userFK")
private List<TwitterAccount> twitterAccounts;
/* GETTERS & SETTERS OMITTED */
}
And then I have the TwitterAccount class:
#Entity
public class TwitterAccount extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
private User userFK;
}
What happens is that when it tries to get the Twitter accounts for a certain user, I get the exception: MySQLSyntaxErrorException: Unknown column 'twitteracc1_.userFK_id' in 'field list'
Look at what it tries to map the userFK to: userFK_id. Of course it doesn't exist! I haven't given it that name.
So the question comes down to: Is it possible to turn off this functionality? (The functionality that turns the column name into 'field_'foreignkey')
I am aware that using #JoinColumn(name = "userFK") would solve it, but I'd rather turn it off instead.
Regards
This is the default as specified by the JPA specification
The concatenation
of the following: the name
of the referencing relationship
property or field of the referencing
entity or embeddable class;
""; the name of the referenced
primary key column. If there is no
such referencing relationship
property or field in the entity, or if
the join is for an element collection,
the join column name is
formed as the concatenation of the
following: the name of the entity;
""; the name of the referenced
primary key column.
In hibernate this is implemented in a NamingStrategy in this case the EJB3NamingStrategy. You can implement your own version of this deciding whatever you want to use. But that will probably only complicate/confuse people (which might expect the standards to apply).

Categories