Hibernate: foreign keys instead of list of entites - java

There is already a solution - how to store fk instead the whole entity on many-to-one unidirectional:
#JoinColumn(name = "message_key")
#ManyToOne(targetEntity = Messages.class, fetch = FetchType.LAZY)
private Messages message;
#Column(name = "message_key", insertable = false, updatable = false)
private Long message_fk;
Two questions:
How to do the same for unidirectional many-to-many? Means I have a List<Message> messages and want to keep only List<Long> message_fks.
Will it ensure consistency if I will never use message object? I want to use only message_fk field.

Related

Multiple Spring JPA relationships between 2 entities

I have 2 entities, one for a taskList and the other for users. The users can create tasks for themselves or their friends, so in the Tasks entity I have different columns referencing the User entity, one for createdBy another for createdFor and a last one for modifiedBy.
In the tasks entity I made the following #ManyToOne JPA relationships:
#ManyToOne(optional = false)
#JoinColumn(name = "created_by", nullable = false,
referencedColumnName = "id")
private User createdBy;
#ManyToOne
#JoinColumn(name = "created_for", nullable = false,
referencedColumnName = "id")
private User createdFor;
#ManyToOne
#JoinColumn(name = "modified_by", nullable = false,
referencedColumnName = "id")
private User modifiedBy;
But I am not sure how to do the linking in the Users side, I had the following #OneToMany relationship:
#OneToMany(mappedBy = "createdFor", cascade = CascadeType.ALL)
private List<Task> taskList;
But I am not sure how to proceed with the other relationships as I don't really need a taskList for the tasks that a user created, or what tasks did he modify.
You do not need to map all things in an Entity , and also do not need to configure every relationships as bi-directional.
So if you really do not need to access the Tasks that are created and modified from a given User , just ignore them and do not map them in User.
It is perfectly valid to configure a relationship as unidirectional. Your existing codes should already work perfectly.

Strategy to use the same UUID across multiple entities

I have an entity classes in JPA as below in which maId acts as a primary key and foreign key for many other tables.
#Table(name = "Table1")
public class Test implements Serializable {
#Id
#Column(name = "maId", updatable = false, nullable = false)
private String id;
#OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="maId")
private MFieldData fieldData;
#OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="maId")
private MPS mps;
#OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="maId")
private MJob mJob;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="maId")
private List<MExtension> mlExtensions;
private Date createdDate;
private Date lastUpdatedDate;
}
Now,this is my another entity.
#Table(name = "table 2")
public class Test implements Serializable {
#Id
#Column(name = "maId", updatable = false, nullable = false)
private String maId;
private Integer cmd;
private String routeId;
}
By the time I receive a request this is API. I need to Insert the data across multiple tables.
How to implement a custom UUID (maId) generator and use it in #Id?
I need to use the same maId which is the unique id for this request across multiple entities while inserting into the DB. I am using a dirty way to do that. But is there any JPA way to solve this problem?
Any help would be highly appreciated!
The request has to pass the UUID (Called correlation-id) to track. https://docs.oracle.com/javase/7/docs/api/java/util/UUID.html can be used. If you generate in code it may go unknown to caller. The correlation-id is used to track the request data across systems it may travel due to event publish as well.

JPA merge on auto increment

I have an Entity that has the following multiple fields along with a field that is autogenerated on an insert
Now everytime I want to do an update using merge() in my DAO, it will add a new entry instead of updating the current entry. I am assuming this is due to UPDATE statement on id and the id is new everytime. Is there a way within JPA (Hibernate) to avoid writing a new record in the database and just to an update instead. Please find below my entity object:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "CONFIG_ID")
private long configID;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "CID", referencedColumnName = "CID", insertable = true, updatable = false),
#JoinColumn(name = "DID", referencedColumnName = "DID", insertable = true, updatable = false)})
#Version private <Object> dE;
#Column(name = "HISTORY", nullable = false, unique = false)
private String history;
merge() is supposed for detached entity use . It is an update or insert action depending if the identity of the merged object is null or not. If it is null , a new record will be inserted.
To correctly update an entity in JPA , you simply load it and change its properties. When the transaction commit , JPA will figure out if there are any properties changes and issue the UPDATE SQL if there are changes. No need to call any methods on EntityManager for any update.
Reference:
JPA wiki - Merge

Hibernate deletes a record, but the record doesn't go away?

EDIT: Oops, I guess it would help if I posted the delete code. Sorry.
// delete from permanent store and local list
int index = get_record_to_delete();
if (entityList.getEntities().get(index).getEntityId() != null ) {
// existing persisted record
entityService.delete(entityInfo.getEntities().get(index).getEntityId());
}
//remove from local list
entityList.getEntities().remove(index);
return ownersInfo;
// entityService called by above code
public void delete(MyEntity entity) {
repository.delete(entity); // subclass of org.springframework.data.jpa.repository.JpaRepository
}
I'm using Spring Data/JPA V 1.4.2.RELEASE and hibernate 3.6.10.Final.
I have a situation where I'm deleting an entity, and delete appears to work, but when I refresh my web page, the entity reappears. So, it doesn't produce an error, but the record doesn't get deleted.
This entity has child entities contained within it. I suspect that some kind of entity dependence problem is keeping the entity from being truly "deleted", but I don't know which entity dependency it might be, and Hibernate's not telling me. It doesn't matter if the contained entities get deleted or not, but this entity needs to get deleted. Not sure why that's not happening. Here's the entity I'm trying to delete:
public class MyEntity implements java.io.Serializable {
#Id
#GeneratedValue
#Column(name = "MYID", unique = true, nullable = false)
private Long myId;
#Column(name = "MY_NAME", nullable = false, length = 50)
private String myName;
#ManyToOne
#JoinColumn(name = "ADDRESS_ID", nullable = false)
private AddressEntity myAddress;
#ManyToOne
#JoinColumn(name = "OTHER_ADDRESS_ID", nullable = true)
private AddressEntity myOtherAddress;
#ManyToOne
#JoinColumn(name = "TYPE_CODE", nullable = false)
private MyType myType;
#ManyToOne
#JoinColumn(name = "ADDRESS_CODE", nullable = false)
private AddressCode addressCode;
#Column(name = "OTHER", nullable = false, precision = 3, scale = 0)
private Integer myOther;
#ManyToOne
#JoinColumn(name = "PARENT_ID", nullable = false)
private MyParent parent;
#Column(name = "PHONE", nullable = false, precision = 10, scale = 0)
private Long myPhone;
#Column(name = "SOCIAL", nullable = false, length = 9)
private String mySocial;
}
Anyone see anything that might suggest why this entity won't delete?
This turned out to be a case of a Hibernate #OneToMany annotation canceling the delete.
Because the parent object had a #OneToMany(cascade=CascadeType.ALL) annotation on it, like this:
Class MyParent {
#OneToMany(cascade=CascadeType.ALL)
Set<MyObject> myObjects;
}
Hibernate apparently walks the entire object graph and for some reason, because this parent wasn't being deleted, it canceled the child delete.
The thing to do to detect this is turn your logging all the way up to TRACE and look for the following message from Hibernate:
un-scheduling entity deletion
Those are the magic words that let you know that Hibernate is canceling your delete. This was not particularly well documented, so I hope this helps someone else.
In your mapping class use this cascade type. It will delete the records from database.
#OneToMany(cascade=CascadeType.ALL)

Using a JoinColumn Twice for CompositeKey getting Repeated Column Exception

I have the following situation:
I´m trying to build an application which is multi-tenant with the same tenants in one database
with the same tables. As by know Hibernate is not supporting this variant before 5.0 as I found.
I`m trying to solve this by adding a brandId field to every table.
As I build Many To Many relationships I also added this brandId to the ManyToMany Join Table and here (dont know if I can do this, mysql is not complaining) I made a foreign key to both tables while both include the brandid
So now for example I have a table Text(ID,name,brandId) and a Tag(ID,name,brandId) and a join table (text_id,tag_id,brand_id) where the foreign keys are
CONSTRAINT FK_TAG_TEXTS_TAG FOREIGN KEY (TAG_ID,BRAND_ID) REFERENCES TAG (ID,brand),
CONSTRAINT FK_TAG_TEXTS_TEXT FOREIGN KEY (TEXT_ID,BRAND_ID) REFERENCES TEXT (ID,brand)
As you can see Brand ID is used twice.
Then I generated my classes with Hibernate Tools, which created a Composite Primary Key Class as it should and the association in the Tag Class.
#ManyToMany(fetch = FetchType.EAGER,cascade = {CascadeType.PERSIST,CascadeType.MERGE })
#JoinTable(name = "tag_texts", , joinColumns = {
#JoinColumn(name = "TAG_ID", nullable = false, insertable = false, updatable = false),
#JoinColumn(name = "BRAND_ID", nullable = false, insertable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "TEXT_ID", insertable = false, nullable = false, updatable = false),#JoinColumn( name = "BRAND_ID", insertable = false, nullable = false, updatable = false) })
public List<Text> getTexts() {
return this.texts;
}
The problem is now that I get the following exception:
org.hibernate.MappingException: Repeated column in mapping for collection: de.company.domain.Tag.texts column: brand_id
I looked into the Hibernate code in the Collection class which raises the exception.
Here a method 'checkColumnDupliation' is called which uses a Set and inserts the name,
what means that a second time inserting "BRAND_ID" as column leads to this behaviour.
As I found the most common solution for the Repeated column error is by inserting 'insertable = false and updateable = false' when using the same column in several references. This is described here:
Hibernate: Where do insertable = false, updatable = false belong in composite primary key constellations involving foreign keys?
But this seems to be not the same problem as mine.
So my question is: Is there a possibility to fix this with the JPA Annotations and use the Brand ID in both joinColumns and inverseJoinColumns?
The problem is that you want a JoinTable between 3 entities: Text, Tag and Brand.
Probably you will have to use an IdClass, something like :
public class AssociationId implements Serializable {
private long textId;
private long tagId;
private long brandId;
hash and equals function
...
}
Id Class Entity:
#Entity
#Table(name="tag_text_brand")
#IdClass(AssociationId.class)
public class TagTextBrandAssociation {
#Id
private long tagId;
#Id
private long textId;
#Id
private long textId;
#ManyToOne
#PrimaryKeyJoinColumn(name="TAG_ID", referencedColumnName="ID")
private Tag tag;
#ManyToOne
#PrimaryKeyJoinColumn(name="TEXT_ID", referencedColumnName="ID")
private Text text;
#ManyToOne
#PrimaryKeyJoinColumn(name="BRAND_ID", referencedColumnName="ID")
private Brand brand;
...
}
You can use this in your 3 entities like this:
#Entity
public class Text {
#Id
private long id;
...
#OneToMany(mappedBy="text")
private List<TagTextBrandAssociation> tagsAndBrands;
...
}
See here for more information.

Categories

Resources