How to map one entity to different table - java

There is my class TableOne.java:
#Table(name = "table_one")
#EntityListeners(AuditingEntityListener.class)
public class TableOne {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator")
#Column(name = "id", unique = true, nullable = false, updatable = false)
private String id;
#CreatedDate
#Column(name = "created", nullable = false, updatable = false)
private LocalDateTime created;
#LastModifiedDate
#Column(name = "modified", nullable = false)
private LocalDateTime modified;
#Column(name = "status_desc")
private String statusDesc;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(table = "callers")
private Party caller;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(table = "callee")
private Party callee;
...getter/setter
}
And there is Part.java:
#Entity
public class Party {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, updatable = false)
private long id;
#Column(name = "desc")
private String desc;
#Column(name = "ip")
private String ip;
#Column(name = "port")
private int port;
}
The following fields: caller, callee inside TableOne.java contains the same fields (id,desc, port, ip), so I want to keep these in two different tables. For example inside callee and caller tables.
How I can do that?

You can use two entities for that. Simply remove #Entity annotation from Party and annotate it with #MappedSuperclass. Then you can create two entities:
#Entity
#Table(name = "caller")
public class Caller extends Party
and
#Entity
#Table(name = "callee")
public class Callee extends Party
Both will have the same fields, but will be mappet to two different tables.

Related

Spring Boot: How to create an Entity with a composite key

I was creating my classes for a project using a chart for practice purposes until I stumbled upon this order_items:
I had no problem creating an Entity like Orders or Products because I knew that for Orders I just had to do something like:
#Entity
#Table(name = "orders")
public class Orders {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "order_id")
private Integer orderId;
// rest of the code...
}
And for for Products something like:
#Entity
#Table(name = "products")
public class Products {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "product_id")
private Integer productId;
// rest of the code...
}
But the table order_items has the variables order_id and item_id, does that count as a composite key? If that is the case, how should those variables look in my OrderItems class?
#Entity
#Table(name = "order_items")
public class OrderItems {
#Column(name = "order_id")
private Integer orderId;
#Column(name = "item_id")
private Integer itemId;
// rest of the code...
}
I've checked different questions and they mention using #IdClass or #EmbeddableId for composite keys, but I'd like to confirm first if that is what I should do in this situation, unless it's not the case, maybe there are more approaches.
I'd really appreciate opinions and/or any article related to this, thank your for your time.
As you mentioned you can use #EmbeddableId.
Here is example :
#Embeddable
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(toBuilder = true)
public class OrderItemsPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(insertable = false, unique = false, updatable = false, nullable = false,name = "order_id")
private Long orderId;
#Column(insertable = false, unique = false, updatable = false, nullable = false,name = "products_id")
private Long productsId;
}
And the Order Items Class.
#Entity
public class OrderItems {
#EmbeddedId
private OrderItemsPK id;
#OneToOne
#JoinColumn(name = "products_id", nullable = false, unique = false, insertable = false, updatable = false, referencedColumnName = "products_id")
private Products products;
#OneToOne
#JoinColumn(name = "orders_id", nullable = false, unique = false, insertable = false, updatable = false, referencedColumnName = "orders_id")
private Order order;
private Long itemId;
}

How to ignore update or insert join if NULL value

I have a entity bean with a relation #ManyToOne that is in join on one column.
#Entity
#Table(name = "work_order")
public class WorkOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#NotNull
#Column(name = "id_order", nullable = false)
private String idOrder;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private StatusOrder status;
#Column(name = "creation_date")
private Instant creationDate;
#Column(name = "closing_date")
private Instant closingDate;
#Column(name = "client_id")
private Long clientId;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) #NotFound (action = NotFoundAction.IGNORE)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "account", insertable = false, updatable = false, nullable = true)
private AnagraficaClienti account;
And the second Entity
#Entity
#Table(name = "es_account")
public class AnagraficaClienti implements Serializable {
private static final long serialVersionUID = 1L;
// da rimettere a #NotNull
#Column(name = "fk_cod_azienda", nullable = true)
private String fk_cod_azienda;
#Id
#NotNull
#Column(name = "account", nullable = false)
private String account;
// da rimettere a #NotNull
#Column(name = "tipo_cli_for", nullable = true)
private String tipoClienteFornitore;
#Column(name = "tipo_account", nullable = true)
private String tipoAccount;
....
The "es_account" table has three not nullable primary key(fk_cod_azienda, account, tipo_cli_for) and the relation with the "work_order" table is by account column.
My problem is that sometimes it is possible that the user insert or update WorkOrder with a null account value and that is not avoid by AnagraficaClienti entity because it expects a non null(and not duplicate) value.
Are there any possible way to bypass the join with AnagraficaClienti when account is null?
In my point of view, #ManyToOne is violate OOP design principle due to the creation of redundant relation. Instead, i always create a #OneToMany relation with a list of related entities. To specify the relation as nullable, just add the nullable=true property in #JoinColumn. With #ManyToOne, you must specify property optional=true. Lets try and see if it works.
WorkOrder
#Entity
#Table(name = "work_order")
public class WorkOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#NotNull
#Column(name = "id_order", nullable = false)
private String idOrder;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private StatusOrder status;
#Column(name = "creation_date")
private Instant creationDate;
#Column(name = "closing_date")
private Instant closingDate;
#Column(name = "client_id")
private Long clientId;
AnagraficaClienti
#Entity
#Table(name = "es_account")
public class AnagraficaClienti implements Serializable {
private static final long serialVersionUID = 1L;
// da rimettere a #NotNull
#Column(name = "fk_cod_azienda", nullable = true)
private String fk_cod_azienda;
#Id
#NotNull
#Column(name = "account", nullable = false)
private String account;
// da rimettere a #NotNull
#Column(name = "tipo_cli_for", nullable = true)
private String tipoClienteFornitore;
#Column(name = "tipo_account", nullable = true)
private String tipoAccount;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
#JoinColumn(name = "account", nullable = true)
private List<WorkOrder> workOrders;
When you want to insert the work order to the database:
workOrderRepository.save(workOrder);
When you want to create the relationship:
AnagraficaClienti client = anagraficaClientiRepository.findById(...);
client.getWorkOrders().add(newWorkOrder);

I want to know about Hibernate annotation

I have a question about "annotations" in hibernate.
I have a BaseEntity class and another class like state.java who extend
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler", "createdBy", "updatedBy" })
#MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private T id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CreatedBy", nullable = true)
private User createdBy;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "UpdatedBy", nullable = true)
private User updatedBy;
#Column(name = "createdDate", nullable = true, updatable = false)
private Date createdDate;
#Column(name = "UpdatedDate", nullable = true)
private Date updatedDate;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "subsite", nullable = true)
private Subsite subsite;
#Column(name = "ip", nullable = true)
private String ip;
#Entity
#Table(name="State")
public class State extends BaseEntity<Long> {
#Column(name = "state", nullable = true)
private String state;
#Column(name = "city", nullable = true)
private String city;
when program creat my tables in DataBase my table'design build like this:
How can I create a table so that the BaseEntity'fields place after state'fields in my Table

JPA unidirectional one to many with join table - entity mapping not working

I have tried to create some JPA Entities for a DB designed with the following tables: PRINCIPALS and CREDENTIALS which have the following relations with other tables:
#Entity
#Table(name = "CREDENTIALS")
public class Credentials {
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#OneToOne
#JoinColumn(name = "CREDENTIAL_TYPE_ID", insertable = false, updatable = false)
private CredentialTypes credentialTypes;
}
CREDENTIALS has a oneToOne relation with CREDENTIAL_TYPES
#Entity
#Table(name = "CREDENTIAL_TYPES")
public class CredentialTypes {
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#Column(name = "DESCRIPTION")
private String description;
}
#Entity
#Table(name = "PRINCIPALS")
public class Principals implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#OneToOne
#JoinColumn(name = "PRINCIPAL_TYPE_ID", insertable = false, updatable = false)
private PrincipalTypes principalTypes;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "PRINCIPAL_CREDENTIAL",
joinColumns = #JoinColumn(name = "CREDENTIAL_ID"),
inverseJoinColumns = #JoinColumn(name = "PRINCIPAL_ID"))
private List<Credentials> credentials;
PRINCIPALS has a oneToOne relation with PRINCIPAL_TYPES
#Entity
#Table(name = "PRINCIPAL_TYPES")
public class PrincipalTypes implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "DESCRIPTION")
private String description;
And finally PRINCIPALS has a oneToMany relation with CREDENTIALS and uses a join table PRINCIPLE_CREDENTIAL
#Entity
#Table(name = "PRINCIPAL_CREDENTIAL")
public class PrincipalCredential implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Id
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
At startup (using SpringBoot) I receive an error for the oneToMany relation between Principals and Credentials and just don't have any idea how to fix it... Tried various other methods (The DB design cannot be changed).
Caused by: org.hibernate.AnnotationException: A Foreign key refering entities.Principals from entities.Credentials has the wrong number of column. should be 2
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:502)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1467)
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1233)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:794)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:729)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:85
I find the exception wierd because there is no refering of Principlas from Credentials....
PRINCIPLE_TYPE_ID and CREDENTIAL_TYPE_ID are missing in the joinColumns/inverseJoinColumns. I think you must use the #JoinColumns Annotation

Netbeans #JoinColoumns error with auto generated entity class

I've creating entities from a data-source using Netbeans 7.4.
And I have an error which arises with all entities which have a composite primary key. The error can be seen below.
I have searched this problem on stack-overflow and its is usually because people have not defined the join columns. but I have this done. I'm also unsure how there is errors in code generated by netbeans.
Here is an image of my MySQL database which I forward engineered to create these entitys:
Any help would be greatly appreciated !
Here is the only the relevant code
Absence entity:
public class Absence implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected AbsencePK absencePK;
#Basic(optional = false)
#NotNull
#Column(name = "idAbsence")
private int idAbsence;
#Basic(optional = false)
#NotNull
#Column(name = "Date")
#Temporal(TemporalType.DATE)
private Date date;
#Size(max = 35)
#Column(name = "type")
private String type;
#Lob
#Size(max = 65535)
#Column(name = "remark")
private String remark;
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Timetable timetable;
#JoinColumn(name = "Student_idStudent", referencedColumnName = "idStudent", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Student student;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
AbsencePK entity:
#Embeddable
public class AbsencePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
#Basic(optional = false)
#NotNull
#Column(name = "Student_idStudent")
private int studentidStudent;
#Basic(optional = false)
#NotNull
#Column(name = "TimeTable_Period")
private int timeTablePeriod;
public AbsencePK() {
}
public AbsencePK(int classidClass, int studentidStudent, int timeTablePeriod) {
this.classidClass = classidClass;
this.studentidStudent = studentidStudent;
this.timeTablePeriod = timeTablePeriod;
}
Error:
Caused by: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field timetable] from the entity class [class com.fyp.simstest.Absence] is incomplete.
When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns.
Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1847)
EDIT
TimeTable
#Entity
#Table(name = "timetable")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Timetable.findAll", query = "SELECT t FROM Timetable t"),
#NamedQuery(name = "Timetable.findByPeriod", query = "SELECT t FROM Timetable t WHERE t.timetablePK.period = :period"),
#NamedQuery(name = "Timetable.findByDay", query = "SELECT t FROM Timetable t WHERE t.timetablePK.day = :day"),
#NamedQuery(name = "Timetable.findByClassidClass", query = "SELECT t FROM Timetable t WHERE t.timetablePK.classidClass = :classidClass")})
public class Timetable implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TimetablePK timetablePK;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "timetable")
private Collection<Absence> absenceCollection;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
public Timetable() {
}
public Timetable(TimetablePK timetablePK) {
this.timetablePK = timetablePK;
}
TimetablePK
Embeddable
public class TimetablePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Period")
private int period;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "Day")
private String day;
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
public TimetablePK() {
}
public TimetablePK(int period, String day, int classidClass) {
this.period = period;
this.day = day;
this.classidClass = classidClass;
}
EDIT TWO
Your diagram indicates the TimeTable table has a primary key composed of three columns (Period, Day, and Class_idClass). You will need to add an annotation to Absence.timeTable that looks something like this:
public class Absence implements Serializable {
...
#JoinColumns[
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", ...),
#JoinColumn(name = "????", referencedColumnName = "Day", ...),
#JoinColumn(name = "Class_idClass", referencedColumnName = "Class_idClass", ...)
]
#ManyToOne(optional = false)
private TimeTable timeTable;
...
}
Consider this:
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period")
private Timetable timetable;
You have referenced to the column Period at your Timetable entity. But in the Timetable.java I don't see any field that is mapped with your Period column of your table.
For example:
#Id // as its the primary key!
#Column(name="Period")
private Long period
This should be same for other referenced entities those you have used with your #ManyToOne mapping.

Categories

Resources