Hibernate JPA uniqueness - java

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

Related

jpa - Multiple #ElementCollection in two different #Embeddable classes

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,

Mapping one DB column to two seperate fields using JPA

I'm developing a code generator that have to generate JPA entities from database meta-model files. These model are from home-brewed modeling system which are being used to generate models other than JPA entities.
In these models some fields are mapping back to same database column. But it seems like JPA does not like that very much. When I try to run generated code I get
Exception [EclipseLink-48] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [FACT_INVENT_TRANS_HIST_DM.TRANSACTION_ID]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[TransactionIdKey-->FACT_INVENT_TRANS_HIST_DM.TRANSACTION_ID]
Descriptor: RelationalDescriptor(InventTransHistFactDM --> [DatabaseTable(FACT_INVENT_TRANS_HIST_DM)])
As I can't change the models only option left is to make one of those fields read-only. And the JPA entities being generated are only used to read data from database it will not used for writing data. Is there a way to mark some fields as read only or tell EclipseLink that these entities are read only so it does not have to worry about the multiple writable mapping.
I tried using EclipseLink's #ReadOnly annotation in all entities but it did not help this issue.
There is no #ReadOnly in JPA.
There are however attributes "insertable"/"updatable" that you can set against a field via #Column to effectively do the same.
The question may be almost 6 years old, but it's still being found today, so I'd like to address another option:
public class Foobar {
#OneToOne
#JoinColumn(name="SELF_COLUMN_FOO", referencedColumnName = "FOREIGN_COLUMN_TO_JOIN")
public Foo foo;
#OneToOne
#JoinColumn(name="SELF_COLUMN_BAR", referencedColumnName = "FOREIGN_COLUMN_TO_JOIN")
public Bar bar;
}
This can be used where SELF_COLUMN is obviously the relevant column in the Foobar table, and FOREIGN_COLUMN_TO_JOIN would be single key in the other table you wish to join.
This will be useful where you want to have two (or more) attributes in a single class, but only one column to join on the foreign DB table. For example: An Employee may have a home phone number, cell number, and a work phone number. All are mapped to different attributes in the class, but on the database there's a single table of phone numbers and id's, and an identifier column, say VARCHAR(1) with 'H' or 'W' or 'C'. The real example would then be...
Tables:
PHONENUMBERS
PHONENUMBER_ID,
ACTUAL_NUMBER
EMPLOYEE
ID
HOMENUMBER VARCHAR(12),
CELLNUMBER VARCHAR(12),
WORKNUMBER VARCHAR(12)
public class Employee {
#OneToOne
#JoinColumn(name="HOMENUMBER", referencedColumnName = "PHONENUMBER_ID")
public Phone homeNum;
#OneToOne
#JoinColumn(name="CELLNUMBER", referencedColumnName = "PHONENUMBER_ID")
public Phone cellNum;
#OneToOne
#JoinColumn(name="WORKNUMBER", referencedColumnName = "PHONENUMBER_ID")
public Phone workNum;
}
As you can see, this would require multiple columns on the Entity's table, but allows you to reference a foreign key multiple times without throwing the 'Multiple writable mappings exist...' that you showed above. Not a perfect solve, but helpful for those encountering the same problem.

Hibernate Inheritance.JOINED generated FK name

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.

How to tell Hibernate to conditionally ignore columns in CRUD operations

Is it possible to somehow tell Hibernate to conditionally ignore a missing column in a database table while doing the CRUD operations?
I've got a Java application using Hibernate as persistence layer. I'd like to be able to somehow tell Hibernate: If database version < 50, then ignore this column annotation (or set it transient).
This situation arises due to different database versions at different clients, but same entity code for all sites. For example, I've got a class, where the column description2 might miss in some databases.
#Entity
#Table(name = "MY_TABLE")
public class MyTable implements java.io.Serializable {
private Integer serialNo;
private String pickCode;
private String description1;
private String description2;
#Id
#Column(name = "Serial_No", nullable = false)
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
public Integer getSerialNo() {
return this.serialNo;
}
#Column(name = "Pick_Code", length = 25)
public String getPickCode() {
return this.pickCode;
}
#Column(name = "Description1")
public String getDescription1() {
return this.description1;
}
#Column(name = "Description2") // <- this column might miss in some databases
//#TransientIf(...) <- something like this would be nice, or any other solution
public String getDescription2() {
return this.description2;
}
}
Background: I have a large application with a lot of customizations for different clients. Now it happens from time to time that one client (out of lets say 500) gets a new feature that requires a database structure update (e.g. a new field in a table). I release a new version for him, he runs a database schema update and can use the new feature. But all other clients won't do an incremental database update each time when any user gets a new feature. They just want to use the latest version, but are affected by the new feature (for that one client) they will never use.
I think it is only possible if you separate the mapping definition from the entities so that you can replace it. Thus you can not use annotation based mapping.
Instead I would suggest to use xml based mapping and create different xml mapping files for each client. Since you have about 500 clients you might want to create groups of clients who all share the same mapping file.
At least I think it will be very hard to maintain the different clients needs with one entity model and it will lead to a complex code structure. E.g. if you add properties to the enties that can be null for some clients than you will also add a lot more null checks to your code. One null check for each client specific property.

Use of Java constructors in persistent entities

I'm new to JPA and using persistence in Java anyway and I have two questions I can't quite work out: I have generated tags as:
#JoinColumn(name = "UserName", referencedColumnName = "UserName")
#ManyToOne(optional = false)
private User userName;
#JoinColumn(name = "DatasetNo", referencedColumnName = "DatasetNo")
#ManyToOne(optional = false)
private Dataset datasetNo;
But in one of the constructors for the class, no reference is made to columns UserName or DatasetNo whereas all other columns in the class are referenced in the constructor.
Can anyone tell me why this is? Both columns UserName and DatasetNo are 'foreign keys' on the entity Visualisation which corresponds to a database table of the same name. I can't quite work out the ORM.
And when using entity classes, or POJO, is it better to have class variables like:
private User userName;
Where an instance of a class is specified or simply the key of that class instance like:
private String userName;
Thanks
Mr Morgan.
The way the constructor was written is just a feature of whichever auto-generation tool you used to create your classes from the schema. If you want a constructor that takes them, feel free to add it. Would need to know which one you used and how it was configured to comment on why it worked that way :)
It's normally preferrable to have the actual object relationships mapped. That is the entire point of ORM afterall, no? To have an actual, usable domain of objects that maps to what's in the database, rather than dumb structs that require further manipulation to be made into usable business objects. You'll also need them if you want to be able to write object queries sensibly.
It's much nicer to write:
Select roles from UserRoles roles where role.user.isAdmin = true
than
Select roles from UserRules roles join Users u on roles.userName = u.userName where u.isAdmin = true
Depending on your display technology it can also be helpful for view binding to have real object relationships.
Do note the property names created by your autogeneration tool are also arbitrary. There is no requirement they match the column names.
public User getUserName() is in fact rather silly.
You can certainly change it to public User getUser()
First of all, per specification, an entity must have a public or protected no-arg constructor. It may have other constructors but JPA doesn't care of them so feel free to add whatever you want/need as long as you provide a no-arg constructor.
Secondly, when working with an ORM, you need to "forget columns and foreign keys" and think objects and associations, the ORM will take care of foreign keys and joins for you.
So I would actually expect to see something like this:
#JoinColumn(name = "UserName", referencedColumnName = "UserName")
#ManyToOne(optional = false)
private User user;
#JoinColumn(name = "DatasetNo", referencedColumnName = "DatasetNo")
#ManyToOne(optional = false)
private Dataset dataset;
The difference is subtile (erf, there is technically no difference) but fundamental in what it communicates: attributes of your entities are not foreign keys but instances of other entities (hence the think object and associations).
The same applies when writing queries using JPQL. You need to think object and to navigate through associations. For example, to retrieve in JPQL the userName of a User for a given... well, let's call Foo the entity holding User and Dataset here:
select f.user.userName from Foo f where f.id = :id

Categories

Resources