I am implementing solution to office relocation. One of the main task is to show where assets/furniture should be moved. I have an entity like this (shorted version):
#Entity
#Table
class Asset extends BaseEntity{
private String name;
#Embedded
private Localization localization;
Localization contains Floor (floor_id, floor_name), x_axis, y_axis;
Here is a graphic representation of my problem (on frontend side).
How I can keep current and next (destination) localization in database? I've tried some ways but they did not work. Like here:
#Entity
#Table
class Asset extends BaseEntity{
private String name;
#AttributeOverrides({
#AttributeOverride(name="floor.id", column=#Column(name="current_floor_id")),
})
#Embedded
private Localization localization;
#AttributeOverrides({
#AttributeOverride(name="floor.id", column=#Column(name="destination_floor_id")),
})
#Embedded
private Localization destinationLocalization;
But it yells at me that floor_id is not unique and should be inserted=false and updatable=false.
Another way that I've tried was #OneToOne relation with new entity Column, or even joining in query without relations.
I've heard about Hibernate Envers, maybe that is solution?
If you need just 2 locations, I would suggest you use the approach you already mentioned i.e. keep both old and current location infos in the entity.
If you need a history, you could create an entity e.g. AssetLocation with a surrogate id and refer to that in the Asset. Just don't delete the old AssetLocation objects, then you can create a one-to-many association to refer to the old positions.
You could use envers as well, but there are some limitations you have to be aware of which you can read about in the documentation.
Related
I'm trying to create a favorites mapping and I'm somewhat confused on how to do it,
Here is my user class, for the sake of clarity it has only 2 bindings(1st one(file) - #OneToMany, 2nd one(favorite file) - #ManyToMany.
#OneToMany(mappedBy = "app_user")
#JsonIgnoreProperties("app_user")
private List<File> file;
#ManyToMany(mappedBy = "app_user")
#JsonIgnoreProperties("app_user")
private Set<File> favorite_file;
And I've just realized that intellij complains about it for some reason.
it tries to connect only to 1 field on the other side:
#JsonIgnoreProperties({"file", "profile"})
#ManyToOne
private AppUser app_user;
what would be a better way to do this? because Intellij complains about it and it works but only with native queries(since JPA claims that there is no difference between files and favorite files, but in native query there is a ManyToMany table so it works there)
My goal is to make users have favorite files distinct from files.
It tries to connect only to 1 field on the other side
Well with #OneToMany(mappedBy = "app_user") you explicitly tell it to map it to the same field.
Which doesn't make sense, because
why would you have the same relation represented twice in one entity
The relationship types don't match. You can't have one relationship be ManyToOne from the one side and in the inverse direction be ManyToMany
It looks you have some clarification to do on what you want to represent by your model.
I see multiple possible variants.
The general mapping in AppUser is correct
So an AppUser has multiple File instances but each File is only owned by a single AppUser (if at all).
But an AppUser favorites many files and each File might be favoured by many users.
#Entity
class AppUser {
#OneToMany(mappedBy = "ownedBy")
private List<File> files;
#ManyToMany(mappedBy = "favoredBy")
private Set<File> favoriteFiles;
}
#Entity
class File {
#ManyToOne
private AppUser ownedBy;
#ManyToMany
private Set<AppUser> favoredBy;
}
The important part is that the defining relationships (the one in File) are two distinct relationships.
I removed the JSON annotations, because they are independent of the discussed problem.
Note that it is an interesting discussion if the relationship even should be bidirectional, but that is a different topic.
The favourite files are a subset of the owned files.
Then a more fitting model would be to model favouriting as an attribute of the relationship between AppUser and File
#Entity
class AppUser {
#OneToMany
private List<FileRelation> files;
eFiles;
}
#Entity
class FileRelation {
#ManyToOne
File file;
boolean isFavourite;
}
#Entity
class File {
}
I made the relationships unidirectional and the overall relation between user and file a many to many.
You might want to adapt that to your needs.
Side remark: Please use standard Java naming conventions when coding in Java (no snake case for attributes). Otherwise you are seriously hurting other Java developers.
I have an entity with two Embedded classes of the same type and which one has an ElementCollection of the same type two. The business logic is apparently correct, but I am experiencing some problems with lack of knowledge in JPA, I guess.
Let's check my classes:
#Entity
public class Etapa extends EntidadeBase {
#Embedded
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
private CronogramaDeDesembolso cronogramaDeDespesa;
}
#Embeddable
public class CronogramaDeDesembolso {
#ElementCollection
private List<Parcela> parcelas;
}
I am receiving the following error log.
Caused by: org.hibernate.HibernateException: Found shared references
to a collection:
nexxus.convenioestadual.dominio.planodetrabalho.etapa.Etapa.cronogramaDeReceita.parcelas
Do you guys have any clue of what is wrong and how can I fix it?
EDIT:
Due comments I did this edit and it do not worked too
#Entity
public class Etapa extends EntidadeBase {
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasReceita"))
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasDespesa"))
private CronogramaDeDesembolso cronogramaDeDespesa;
}
Is there any reason why you have decided to use this structure ? Typically when converting an object to an RDBMS you would need to model the relationships. When you use an embeddable it will add the column (or columns) associated with it to the table. So when you do this normally (not collections) it is fine.
When you do a collection it runs into issues. Mainly there is no way to represent a collection in a single row (since this is an entity you could have many of them so effectively for each object you only have one row) & one column. So when you represent a collection you actually have to have a second table with a column referencing it back to the first. It's really the opposite thinking of a normal object. The collection entries need to know what collection they were associated with instead of the collection being knowledgeable of its entries.
So in some POJO you could have and these....
MyListObject {
//Some implementation of things you want to collect
}
MyClass {
List<MyListObject> myListObject;
}
But to model this in JPA you would need to have these represented by two tables.
Your object that will be in the list.
#Entity
MyListObject {
#ManyToOne
#JoinColumn(name = "MY_CLASS_KEY")
private MyClass myClass;
}
Your object/entity that will have the list.
#Entity
MyClass {
#Id
#Column(name = "MY_CLASS_KEY")
private Long myClassKey;
#OneToMany(mappedBy = "myClass")
private List<MyListObject> myString;
}
I hope this helps.
A quick search on Google turned up this in StackOverflow:
JPA Multiple Embedded fields
It would seem as though you have to do some explicit annotation overriding over the fields within the embeddable class. There are some code examples in the linked answer as well that should give you a good idea of where to go.
Cheers,
Let's say that this is a class that has unique constrained field.
#Entity
public class Thing {
#Column(name = "name", unique = true)
private String name;
#ManyToOne
private Owner owner;
}
Example works just fine if new Things are created with unique names. But when different owners want to create things with the same name this approach fails.
Is it possible to set unique constraint to differ records of Things in the database based on the Owners using Hibernate/JPA functionalities (I could not find any) or should I write my own logic and dump the unique from #Column.
Perhaps it could be done with Hibernate Validator? Reading the docs I haven't found much about unique constraints.
You're looking for #UniqueConstraint
http://docs.oracle.com/javaee/5/api/javax/persistence/UniqueConstraint.html
Been struggling with this one for a couple of days. I've got 2 models course and student. Each model is used as a form to register courses and students. I've created a separate entity called timetable which has a course object and a student object, instead of having a manytomany relationship. Here are the releavant sections of the code
Objects/lists from the class model
#Id
#GeneratedValue
public Long id;
#OneToMany(mappedBy = "course", cascade=CascadeType.ALL)
public List<Timtable> timetable;
Objects/lists from the student model
#Required
#Email
#Id
public String email;
#OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
private List<Timetable> timetable;
Objects from the timetable model
#ManyToOne
#JoinColumn(name="email")
public Student student;
#ManyToOne
#JoinColumn(name="id")
public Course course;
Now, I "add" a course to the timetable through a form. The form has 2 hidden inputs with the email and the id. The mySQL table updates, but with NULL values instead of the values that are populated in the form. If I change the timetable variables from objects to primitive types it updates correctly, but when I change back the objects, and the manytoone/onetomany relationship, it just has NULL again. Any ideas on why this is happening?
I'm new to RDMS and ORMs. I've trawled a fair few resources to get the above code together. This is a good one: http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/22/ (where I got the new class called timetable idea from) and this: http://lazylightening-tech.blogspot.co.uk/2013/07/manytomany-ebean-example.html the Beisar dude has also posted some really good stuff on it. I've been over too many of his posts on here and the google group to get to link, but most people have error messages. I'm not getting an error, it just isn't registering what I'm submitting. Can anyone help?
try writting up manual getters and setters..even i encountered this problem..if you are using eclipse then you can do..
right click + source + generate getters and setters
moreover go through this-
http://www.playframework.com/documentation/2.1.0/JavaEbean
PS - Because Ebean class enhancement occurs after compilation, do not expect Ebean-generated getter/setters to be available at compilation time. If you’d prefer to code with them directly, either add the getter/setters explicitly yourself, or ensure that your model classes are compiled before the remainder of your project, eg. by putting them in a separate subproject.
I am currently trying to use inheritance within Hibernate and came across InheritanceType.JOINED. I like the idea of concentrating all data in one table and sharing IDs rather than having duplicate columns in all the sub type tables (#MappedSuperClass). But Hibernate automatically generates indexes on my sub class tables on the id column like FK_idx3wiwdm8yp2qkkddi726n8o everytime I initialize my Hibernate singleton. I noticed that by hitting the 64 key limit on my MySQL Table as the names are generated differently on every startup.
What is the proper way to handle this? Can this be fixed by annotations? What else could I try?
I know that there are countless similar Questions on SO but haven't been able to identify one solving my specific problem.
I am not going to disable hbm2ddl.auto during dev mode.
I am using MyISAM. There are no actual Foreign Keys. This is why Hibernate generates default indexes, I think. Anyway, the problem would be identical with InnoDB and real Foreign Keys as the names would still be quite random. Or maybe Hibernate would actually check for existence in this case. I don't really see, why it does not do this on MyISAM tables.
As I hit similar problems before, the solution could also be to specify a name for that single-column index. But how?
Super Class: FolderItem
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class FolderItem implements Comparable<FolderItem>
{
#Id
#GeneratedValue
protected int id;
protected String name;
#OneToOne
#ForeignKey(name = "fkParent")
protected Folder parent;
...
}
Sub Class: Folder
#Entity
public class Folder extends FolderItem
{
#OneToMany(mappedBy = "parent")
#OrderBy(value = "sortOrder")
private List<FolderItem> children;
...
}
What I tried
add #Index to FolderItem.id - this created an index on the FolderItem table as one would expect, but didn't affect the Folder table
copy protected int id; to Folder and tried to add an #Index to it, which resulted in an Exception similar to "duplicate definition of ID"
add #Table(appliesTo = "Folder", indexes = { #Index(name = "fkId", columnNames = { "id" }) }) to Folder class, which actually created my specified index as expected, but still created it's own FK_9xcia6idnwqdi9xx8ytea40h3 which is identical to mine, except for the name
Try #PrimaryKeyJoinColumn(name = "foler_item_id") annotation for Folder class.