I am working on a Java web application that I think use Hibernate and I am not so into Hibernate so I have the following doubt:
I have a model class named ReaDichiarazioneIntento that map a database table named REA_DICHIARAZIONE_INTENTO, something like this:
#javax.persistence.IdClass(it.enel.wearea.entity.ReaDichiarazioneIntentoPK.class)
#javax.persistence.Table(name = "REA_DICHIARAZIONE_INTENTO", schema = "EDIWEA")
#Entity
public class ReaDichiarazioneIntento implements Cloneable {
private Integer idDichiarazione;
#javax.persistence.Column(name = "ID_DICHIARAZIONE")
#Id
public Integer getIdDichiarazione() {
return idDichiarazione;
}
public void setIdDichiarazione(Integer idDichiarazione) {
this.idDichiarazione = idDichiarazione;
}
private Integer idCliente;
#javax.persistence.Column(name = "ID_CLIENTE")
#Basic
public Integer getIdCliente() {
return idCliente;
}
public void setIdCliente(Integer idCliente) {
this.idCliente = idCliente;
}
...................................................................
...................................................................
...................................................................
SOME OTHER FIELDS AND RELATED GETTER AND SETTER METHODS
...................................................................
...................................................................
...................................................................
}
Ok I have some doubts about this class. My doubt are:
1) Is it using Hibernate for mapping the class to the database table? Or what? I know that to map a database table to a class I have to do something like:
#Entity
#Table(name = "REA_DICHIARAZIONE_INTENTO")
Why in this project do:
#javax.persistence.IdClass(it.enel.wearea.entity.ReaDichiarazioneIntentoPK.class)
#javax.persistence.Table(name = "REA_DICHIARAZIONE_INTENTO", schema = "EDIWEA")
#Entity
What is the difference between the #Table(name = "REA_DICHIARAZIONE_INTENTO") annotation and the #javax.persistence.Table(name = "REA_DICHIARAZIONE_INTENTO", schema = "EDIWEA") annotation (used in my project)?
2) The second doubt is related to this annotation:
#javax.persistence.IdClass(it.enel.wearea.entity.ReaDichiarazioneIntentoPK.class)
What exactly means?
3) The last doubt is related to the mapping between a class field to a table column on the DB. Why is it done only on the getter method and not directly on the field name?
Tnx
It is using JPA annotations, and Hibernate is a JPA implementation. JPA by itself is just a set of interfaces/annotations, while JPA implementation (like Hibernate) provides meat around those interfaces/annotations. There is no difference between the two annotations, other than specified schema. Hibernate also has its own #Table annotation but it is used for additional information supplied by JPA'a #Table annotation
#IdClass means that the complex primary key is used for this entity
Specifies a composite primary key class that is mapped to multiple fields or properties of the entity.
You can annotate fields or properties (getters), it's up to you. But, #Id mapping dictates what is valid, meaning if you put #Id on field then you must put all other mappings on fields also, and vice versa.
This is using JPA, looks like, not hibernate. Here is the difference according to SO and here is another link
Related
I'm trying to map one specific many to many table on my database as an entity in JPA (cause I have some specific attributes on my relationship table and I wanted to retrieve this as the class attributes two). But having issues while declaring the IDs.
#Data
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Entity
#Table(name = "user_plan")
public class UserPlan implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#OneToOne
private User user;
#Id
#OneToOne
private Plan plan;
private Integer billingDay;
#Enumerated(EnumType.STRING)
private BillingType billingType;
#Enumerated(EnumType.STRING)
private PlanStatus planStatus;
}
The application starts successfully but when I try to map some repository to manage this table, Hibernate throws an error:
java.lang.IllegalArgumentException: This class [class com.demo.domain.model.UserPlan] does not define an IdClass
How can I use the JPA entity annotation to manage this relationship table? Is it possible?
I cannot simply declare one property in the user class of Plan model and mark it as #ManyToMany, cause the plan table does not have the property that I need to execute some operations, which are declared on UserPlan class, also I cannot move these properties to Plan class, cause the Plan table is just a template of a plan, and the UserPlan have all the specific data (billingDay, billingType and planStatus).
JPA supports relationship tables as a Java class? Or it can be mapped only as a property?
Thanks
You are using multiple #Id annotations. To do so you need to create PrimaryKey class:
public class PrimaryKey implements Serializable {
private User user;
private Plan plan;
// Getter and Setter
}
And you need to add #IdClass(PrimaryKey.class) annotation to your entity class.
If you have a Repository don't forget to change id type to PrimaryKey:
public interface YourRepository
extends SomeRepositoryInterface<UserPlan, PrimaryKey> {
//...
}
Also check this question
I have below Hibernate relations in a spring boot application.
#Entity
#Table(name = "projects")
public class Project {
#Embedded
private ProjectParameters parameters;
}
#Embeddable
public class ProjectParameters {
#Column(name = "hvacConfigs")
#ElementCollection(targetClass = HVACUserConfigModel.class)
#CollectionTable(uniqueConstraints = #UniqueConstraint(columnNames = {}), foreignKey = ForeignKey(name = "project_hvacConfig_fk"))
private Set<HVACUserConfigModel> hvacConfigs;
}
#Entity
#Table(name = "hvacuserconfig")
public class HVACUserConfigModel {
#Id
#GeneratedValue
private Integer id;
}
Mysql table auto-generated is as follows. Please open images in these below links as I don't have 10 reputation to post images on stackoverflow.
The issue is I am able to save multiple projects with same project like below
Project_uid | hvacConfigs_id
------------------------------
1001 | 1
1001 | 2
Adding (1002 | 1) throws unique constraint violation.
I am able to get it working by changing table definition explicitly using mysql workbench by removing the unique constrain UK_me0ekntab0gknshag0xjjv35x. To remove unique constrain I have to first remove foreign key constrain FKeygabcnr2stdchxqpb5wuinf2 which is being referred by unique constrain. After these changes, I from spring boot app, I insert new rows it is successfully added with values (1002 | 1) & (1002 | 2).
I am able to explore that #CollectionTable annotation, annotated in hvacConfigs field in Java code, provides ways to insert uniqueConstraint and foreignKey definition as part of attribute definition. I have tried tweaking these attributes of annotation but with no success.
Please let me know if you have any solution how to override the unique constraint and foreign key constraints using java code so that this works without any manual adjustment to mysql table explictly.
To be honest, this is unclear what you want to achieve. But your mapping is invalid. You can use #ElementCollection annotation only with basic or embeddable types. If you want operate with HVACUserConfigModel as with an entity you should use #OneToMany association.
So, you can correct your mapping in this way:
#Embeddable
public class ProjectParameters {
#ElementCollection
#CollectionTable(
name = "hvacuserconfig",
joinColumns = #JoinColumn(name = "hvacConfigs_id")
)
private Set<HVACUserConfigModel> hvacConfigs;
}
#Embeddable
public class HVACUserConfigModel {
// #Id annotation is not used with #Embeddable types
// Like basic types, embeddable types do not have any identity,
// being managed by their owning entity.
private Integer id;
// ...
}
or in this way:
#Embeddable
public class ProjectParameters {
#OneToMany
#JoinColumn(name = "hvacConfigs_id")
private Set<HVACUserConfigModel> hvacConfigs;
}
#Entity
#Table(name = "hvacuserconfig")
public class HVACUserConfigModel {
#Id
#GeneratedValue
private Integer id;
}
We solved this using ManytoMany annotation instead of ElementCollection annotation. It works the same way creating new intermediate table to contain Project Id and HVACUserConfigModel id but does not create the unique index.
Is it possible in Spring JPA to map a Transient property of an Object to an alias like so?
Native Query
SELECT *, 1 AS liked FROM User WHERE user_id = 123 // + logic to determine if liked
Class
#Entity
public class User {
#Id
private Long userId;
#Column(name = "displayName")
private String displayName;
#Transient
private int liked; // not tied to any column
}
I've tried to implement this but liked always returns 0 where it should be 1 (and null if I defined the field as an Object type)
Any help is appreciated!
You should use #Formula annotation for the field (see the example)
The #Formula annotation to provide an SQL snippet which Hibernate will execute when it fetches the entity from the database. The return value of the SQL snippet gets mapped to a read-only entity attribute.
I need some help with hibernate annotations.
I have the following 2 entities:
public class Custom {
private Map<KeyObject, ValueObject> properties;
#oneToMany(mappedBy = "customId", cascade = CascadeType.All)
#MapKey(name = "keyObject")
public Map<KeyObject, ValueObject> getProperties();
.....
}
public class ValueObject {
private KeyObject keyObject;
private Long customId;
private String value;
...getters and setters
}
I have a simple dao class to save, update, select, and delete records.
If I remove a record from the map in the Custom object and then call customDao.save(custom) my changes are never persisted to the database. It is not throwing any errors either.
I saw in the hibernate examples I can define the customId as a Custom object instead of a Long in the KeyValue table but I did not want to do this.
Am I setting up my entity's incorrectly?
When an association has the mappedBy attribute, it means: I'm not the owner of this association. Any change done to this side of the association won't matter for Hibernate. What will matter is the other side of the association.
I'm surprised this even works, because I would have expected Hibernate to require a ManyToOne on the other side, of type Custom. But what's sure is that if you don't set the custom/customId field to null in KeyValue/ValueObject, Hibernate won't set this column to null.
My data model represents legal entities, such as a Business or a Person. Both are tax-paying entities, and both have a TaxID, a collection of phone numbers, and a collection of mailing addresses.
I have a Java model with two concrete classes that extend an abstract class. The abstract class has properties and collections that are common to both concrete classes.
AbstractLegalEntity ConcreteBusinessEntity ConcretePersonEntity
------------------- ---------------------- --------------------
Set<Phone> phones String name String first
Set<Address> addresses BusinessType type String last
String taxId String middle
Address Phone
------- -----
AbsractLegalEntity owner AbstractLegalEntity owner
String street1 String number
String street2
String city
String state
String zip
I'm using Hibernate JPA Annotations on a MySQL database, with classes like this:
#MappedSuperclass
public abstract class AbstractLegalEntity {
private Long id; // Getter annotated with #Id #Generated
private Set<Phone> phones = new HashSet<Phone>(); // #OneToMany
private Set<Address> address = new HashSet<Address>(); // #OneToMany
private String taxId;
}
#Entity
public class ConcretePersonEntity extends AbstractLegalEntity {
private String first;
private String last;
private String middle;
}
#Entity
public class Phone {
private AbstractLegalEntity owner; // Getter annotated #ManyToOne #JoinColumn
private Long id;
private String number;
}
The problem is that Phone and Address objects need to refer to their owner, which is an AbstractLegalEntity. Hibernate complains:
#OneToOne or #ManyToOne on Phone references an unknown
entity: AbstractLegalEntity
It seems like this would be a fairly common Java inheritance scenario, so I hope that Hibernate would support it. I've tried changing the mapping for AbstractLegalEntity based on a Hibernate forum question, no longer using #MappedSuperclass:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
However, now I get the following error. When reading up on this inheritance mapping type, it looks like I have to use SEQUENCE not IDENTITY, and MySQL doesn't support SEQUENCE.
Cannot use identity column key generation with <union-subclass>
mapping for: ConcreteBusinessEntity
I'm making more progress toward getting things working when I use the following mapping.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="entitytype",
discriminatorType=DiscriminatorType.STRING
)
I'm thinking I should continue down this path. My concern is that I'm mapping it as an #Entity when I really don't ever want an instance of AbstractLegalEntity to ever exist. I'd like to know if this is the right approach. What is the correct approach I should be taking for this situation?
Use:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
AbstractLegalEntity
In the database you will have one table for AbstractLegalEntity, and tables for classes, which extend AbstractLegalEntity class. You won't have instances of AbstractLegalEntity if it's abstract. Polymorphism can be used here.
When you use:
#MappedSuperclass
AbstractLegalEntity
#Entity
ConcretePersonEntity extends AbstractLegalEntity
This will create only one table in your database called ConcretePersonEntity, containing columns from both classes.
Add #Entity annotation to AbstractLegalEntity. Instance of AbstractLegalEntity will never exist - hibernate will load appropriate extending instances - ConcreteBusinessEntity or ConcretePersonEntity according to Id field.
You have to declare AbstracLegalEntity as an #Entity. Even with the #Entity annotation, your class remains abstract. consequently, you will only have instance of concrete subclasses.