custom constraint while updating Parent Entity Column in hibernate - java

For example I have two tables Employee and Department and I am using
#ManyToOne
#JoinColumn(name = "DEPT_ID", nullable = true, insertable = false, updatable = false)
private Department department;
in Employee.
Here I want to add one constraint that, whenever one of the column of Department is updated to some value then it should not get updated if it has child records in Employee.
Can I achieve this by using CascadeType?
Or is there any other way by which I can define custom constraint?

If your intention is to prohibit memory to database sync when Department is updated, then you're done as you have insertable=false, update=false:
#JoinColumn(name = "DEPT_ID", nullable = true, insertable = false, updatable = false)

Related

best practice for implement ManyToOne

I always use the following method to implement ManyToOne in class :
#Column(name = "buyer_id")
private Long buyerId;
#ManyToOne
#JoinColumn(name = "buyer_id", insertable = false, updatable = false)
UserGroup buyer;
However, I have a question whether it is better to use the following code:
#ManyToOne
#JoinColumn(name = "buyer_id", insertable = false, updatable = false)
UserGroup buyer;
or not?
In the first case, I always set the id value obtained in buyerId for saving after saving the UserGroup, but in the second case, I put the userGroup model completely (after save) in my entity then save entity.
I'm not sure if the method I use is the best.
I searched the internet but could not find a technical reason that the latter is not appropriate.

How to make a collection valued property read only in JPA

I've got a collection valued property of a basic (non-entity) type that I want to make read only. I've managed to exclude the column from insert and update sql queries, but I cannot do the same for delete queries, so if the containing entity has an empty list of said property, all of them get deleted from the database:
#Entity
public class Parent {
#Column(name = "CHILD_ID", insertable = false, updatable = false)
#ElementCollection(fetch = FetchType.LAZY)
#CollectionTable(name = "T_REL_PARENT_CHILD", joinColumns = #JoinColumn(name = "PARENT_ID", insertable = false, updatable = false))
private List<Long> childIds;
}

Hibernate association tables

I have 2 entities that have Id's annotated but those Id's aren the primary keys in the tables. I am still mapping the PK's in to the entity for now to limit the initial impact of the change. But the association table that uses the PK's to associate the many to many relationship is throwing the following error:
java.lang.IllegalArgumentException: Provided id of the wrong type for class. Expected: class java.util.UUID, got class java.lang.Long
The entity #Id is the UUID but the table PK which is a Long is mapped as the #JoinColumn
The composite key for the association entity
#Embeddable
public class CustomerAccountId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "user_id", nullable = false)
private Long customerId;
#Column(name = "account_id", nullable = false)
private Long accountId;
The association entity:
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "customerId", column = #Column(name = "user_id", nullable = false)),
#AttributeOverride(name = "accountId", column = #Column(name = "account_id", nullable = false))
})
private CustomerAccountId id;
#ManyToOne
#JoinColumn(name = "user_id", insertable = false, updatable = false, referencedColumnName = "user_id")
private Customer customer;
#ManyToOne
#JoinColumn(name = "account_id", insertable = false, updatable = false, referencedColumnName = "id")
private Account account;
The failing entity:
#Column(name = "user_id")
private Long serialId; // also the primary key in the table
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#org.hibernate.annotations.Type(type="pg-uuid")
#Column(name = "uid", updatable = false)
private UUID id;
Does anyone know if this is even possible? or am I going to be forced to update the content in the association table when I push this change?
put #Id and #GeneratedValue on the field that represent the table data then hibernate will map a long (sgbd) whit a long (table)
or
your (sgbd) table data type must be compatible with the (java) uuid type.
Why these 2 keys on your table?
I think it's not possible to have 2 PK for one entity. At most you can have a composite key base on your serialID and the UUID.
see How to map a composite key with Hibernate? for that
Or mark as #Id the real PK in the SGBD. Use the other in Java as a classic value in the table's point of view
The solution I decided to go with is the following:
#ManyToOne
#JoinColumns ( value = {
#JoinColumn(name = "user_id", insertable = false, updatable = false, referencedColumnName = "user_id"),
#JoinColumn(name = "user_uid", insertable = false, updatable = false, referencedColumnName = "uid")
})
private Customer customer;
In a nutshell I simply added the UUID to the association table and used both columns for the Customer Entity.
To address #Tokazio's question about using UUID and serial Id, the data warehouse conversion is impacted significantly so I need to slowly move from serial Id's to UUID's to minimize impacts and prevent outages.

Netbeans - Glassfish server deployment error due to composite primary key

I'm currently having an issue with a BUILD FAILED error when deploying my Netbeans project to Glassfish server. I get the following error from the log:
Exception Description: The #JoinColumns on the annotated element [field instrument] from the entity class [class entity.InstrumentExtRef] 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.. Please see server.log for more details.
The table that's having the issue is instrument_ext_ref and has a composite primary key of the following fields: instrument_id and instrument_code_type.
The entity class that seems to have the problem - InstrumentExtRef - has the following declarations and annotations.
#EmbeddedId
protected InstrumentExtRefPK instrumentExtRefPK;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 16)
#Column(name = "reference")
private String reference;
#JoinColumn(name = "instrument_code_type", referencedColumnName = "code_type", insertable = false, updatable = false)
#ManyToOne(optional = false)
private InstrumentCodeType instrumentCodeType1;
#JoinColumn(name = "instrument_id", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Instrument instrument;
And the entity class containing the #EmbeddedId details (InstrumentExtRefPK) looks like this:
#Embeddable
public class InstrumentExtRefPK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "instrument_id")
private int instrumentId;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 10)
#Column(name = "instrument_code_type")
private String instrumentCodeType;
Class InstrumentCodeType refers to table instrument_code_type which has a primary key code_type (the referenced column). Class Instrument refers to table instrument which itself has a composite primary key consisting of columns "id" (the referenced column) and column "exchange_exchange_code".
It seems obvious from the error message that the composite primary key in the InstrumentExtRef entity is the issue but based on my research of other similar (but not quite the same) issues I think my entity classes look OK. But I'm relatively new to this and may be missing something.
After doing some more research on creating/uses of composite keys in entity classes I saw a subtle point in the error message I was receiving.
"...must be specified for each join column using the #JoinColumn*s*". I wasn't using the #JoinColumns annotation. Or at least Netbeans didn't create the entity class that way. Probably because each join column is from a different source entity/table.
After correcting my entity classes as follows the project was able to be deployed successfully.
#JoinColumns({
#JoinColumn(name = "instrument_code_type", referencedColumnName = "code_type", insertable = false, updatable = false),
#JoinColumn(name = "instrument_id", referencedColumnName = "id", insertable = false, updatable = false)})
private InstrumentCodeType instrumentCodeType1;
private Instrument instrument;
It was here that I started to see what the problem might be:
https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/5/html/Hibernate_Annotations_Reference_Guide/ch02s02s06.html
I suspect that my next problem will be something to do with the fact that the composite primary key is made up of columns from two different entities - instrument and instrumentCodeType. But for now the above change got me past the build problem and if that next problem arises I'll deal with it separately.

Unwanted behavior – Hibernate deletes child elements annotated with #ElementCollection when parent element is updated

everyone.
I am have Customer and Service tables in one to many relation - one customer can have no or many services. The Service table has a customer_id column which is a foreign key referencing the primary key of the Customer table.
When retrieving customers from the database I need to get only the IDs of the related services and that is why I decided to use the #ElementCollection annotation.
My mapping for the Customer is as follows:
#Entity
#Table(name = "customer")
public class CustomerEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(nullable = false)
private String name;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "service", joinColumns = #JoinColumn(name = "customer_id", updatable = false, insertable = true))
#Column(name = "id", updatable = false, insertable = true)
private Set<Integer> serviceIds;
}
Everything works perfect when I get data from the database. The problem is when I try to update a customer in the database. Upon update Hibernate deletes all the Service table rows which reference the updated customer if the serviceIds member of the customer entity was set to null or an empty Set. I would like to avoid this behavior. I would like this serviceIds member to be read only for Hibernate and to be ignored when the customer is updated in the database - i.e. I want to update only the customer table and nothing else. Is it possible to achieve this using ElementCollection?
By the way I tried the following mapping and the update of the Customer does not lead to any deletions in the Service table even if I set the serviceIds to null or an empty Set.
#OneToMany
#JoinColumn(name = "customer_id", referencedColumnName = "id", updatable = false, insertable = false)
private Set<ServiceEntity> serviceIds;
Thank You for Your help.
When modifying - even - a single element in an #ElementCollection, Hibernate will delete the old collection (the one persisted in DB) and then insert the new image of the collection. The question was already asked here:
Hibernate - #ElementCollection - Strange delete/insert behavior
In order to avoid this problem you can:
Use a List of Integer with the #OrderColumn annotation as described in the above link.
Create an Entity class wrapping your Integer (+ #Generated #Id).
Best regards

Categories