How do I proceed in terms of Hibernate Annotation (JPA) when a table's primary key column is a foreign key to another table with no auto_increment (MySQL).
Thanks.
Something like the following should work (not tested for exact syntax, but should be close):
#Id
private int id;
#OneToOne
#JoinColumn(name = "id", updatable = false, insertable = false)
private RelationEntity other;
You would need to manually set your 'id' field before you persist it, and can't remember if you can set the 'other' entity before the initial save, hibernate may complain if you do that. However, if your 'id' column is set then when you load the entity back out you should have the relationship loaded as well.
Related
My question is, why do we need a sequence table for table strategy in hibernate inheritance, which id generation must be equal to TABLE? Can't each entity use the IDENTITY column of each table?
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
#Column(updatable = false, nullable = false, insertable = false)
protected int id;
As for the jakarta.persistence.GenerationType javadoc, TABLE is used to indicate the primary keys should be stored in an underlying database table - which is separate from the entities tables - whether you are using inheritance or not.
If you want id to be an IDENTITY column for each table you should use the GenerationType.IDENTITY strategy.
I tried below sample code which does not seem to work, while trying to fetch the object from table, hibernate tries to set the User Object on top of Long objects and fails when tried to load the Parent entity which has this createdBy field
any help?
#JoinColumn(name = "CREATED_BY", referencedColumnName = "USER_ID", updatable = false, nullable = false)
#OneToOne(targetEntity = User.class)
private Long createdBy;
I want to use Long/Integer as type of the field and want to make sure its a valid Foreign key to User table which has Primary key USER_ID
Please note that i DO NOT want to use User as type of my object, for example , i do not want below declaration in my class
private User createdBy;
Edit:
Reason for such requirement:
Ahh well!!, i'll try to keep it short which is basically one of the problem with ORM's like Hibernate. I have a Super Class AuditLogModel which is extended by each and every entity class in my software (100+ entities). This AuditLogModel class has CreatedBy & ModifiedBy field. If i keep the types of this fields as User, then every entity in my software tries to create a join with user table twice on operations like getResultsList/Merge/refresh, where Merge and Refresh calls on entity manger cannot be controlled by us, its all eager loading in one select query. Since my entities have child entities and they have further childs and so on, this creates more than 61 joins and sometime 100+ joins and causes query performance issues. These createdBy and modified by columns are updated with every insert/update but not required with any query when any entity is loaded, and hence I want to avoid the unneccessari joins here. Hope its understood
Ah OneToOne mapping is used for Entities like this:
#JoinColumn(name = "CREATED_BY", referencedColumnName = "USER_ID", updatable = false, nullable = false)
#OneToOne
private User createdBy;
If you want to use just the database value then you must remove the OneToOne mapping:
#Column(updatable = false, nullable = false)
private Long createdBy;
I have created an entity with table name and column names.
I have also added the uniquekey constraint for a column name. But when I run, it shows the following error ;
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "alter table ingredient add constraint
UK_co7ro6kyijhfik027h0y4d3n3 unique (ingredient_name).
java.sql.SQLSyntaxErrorException: Specified key was too long; max key
length is 1000 bytes
After I run the spring boot application, I have tried to add the unique constraint manually in MySQL workbench. - DOES NOT WORK
I have added the below code - DOES NOT WORK
#Table(name = "ingredient", uniqueConstraints=#UniqueConstraint(name="uk_ingredient_name",columnNames="ingredient_name"))
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
Tried to create a table manually in Mysql workbench and tried to alter the column name with unique key later. THIS WORKS. But I want hibernate to do this for me.
#Entity
#Table(name = "ingredient")
public class Ingredient {
#Id
#Column(name="ingredient_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
I want to save the ingredients without any repetitions. I do not want duplicate entries.
I have gone through other answers and none of those solutions helped me.
I tried adding length = 20 in the #column.
It works completely fine without any error.
Could you remove
,unique = true
from #Column annotation and try, it seems there is an hibernate bug .When using unique true it does not obey the naming strategy.
For more information look at this post
#UniqueConstraint and #Column(unique = true) in hibernate annotation
and this one
https://hibernate.atlassian.net/browse/HHH-11586
After removing the unique=true I am able to generate the unique constraint with the specified name that is 'uk_ingredient_name'.Since it is already specified in the #Table annotation.
The error you are getting is because hibernate is generating a unique constraint name which is hitting the allowed limit and it is not taking into the account the constraint name you have declared.
#Column(name="username", length=8, unique=true)
worked fine for me.
I got error:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on xxx.yyy.zz.myentity.xxx_id references an unknown entity: java.util.UUID
code
#ManyToOne
#JoinColumn(name = "xxx_id", nullable = false, updatable = false, referencedColumnName = "xxx_id", insertable
= false)
private UUID xxxId;
I got this when i change from AnotherEntity to UUID. I did this because i dont want to hold an object in my entity but only key to it(key type in AnotherEntity is UUID). I found that this error is cause when Object isnt annotated with
#Entity annotation. Is it true? How can i fix this?
You can represent an Entity as a SQL table and fields (properties) from this Entity as the columns from this table.
That's the easiest way to use Hibernate (or any other JPA implementation).
When you define a relationship (OneToOne, OneToMany, ManyToOne or ManyToMany) you are linking SQL tables so, with JPA, you are linking Entities.
As you can imagine, you can't define a relationship between a table and a column.
So:
your xxxId is supposed to be an object (Entity/Table) mapped in your database and Hibernate must know the column mapping.
that's the purpose of the #Entity annotation and all #Column, #JoinColumn you can use on an Entity class.
so yes, you can't use an object in a ManyToOne relationship that is not annotated with #Entity (it would be considerate by Hibernate like a column)
therefore, you cannot use an object from the JDK (because they are not annotated with any JPA annotation)
more specifically, java.util.UUID is not a class you can change. so you have no way to tell hibernate how it can map it to a Table in your DB.
so the only way I can imagine in your case is to use an entity you created to wrappe the UUID. For example:
#Entity
#Table(name="UUID")
public class UUIDWrapperEntity {
#Id
#Column(name = "UUID")
private UUID uuid;
}
I am developing an application using JPA 2.1 with Hibernate 4.3 as the persistence provider.
For the sacke of readability and better maintainance, I want to explicitly name every possible think and not to rely on the hibernate naming strategy.
I am using the newly introduced #ForignKey annotation to customize the forign key constraint name, and it works fine for #JoinColumn associated with #ManyToOne relationships.
The problem comes when trying to customise the forign key constraints generated for #ManyToMany relationship using a #JoinTable, the provider do not use my provided name, and revert back to its randomly generated name.
for example:
#ManyToOne
#JoinColumn(name = "store_id", referencedColumnName = "id",
foreignKey = #ForeignKey(name = "fk_collection_store_id"))
Store store;
correctly generate the following ddl
alter table collection add constraint fk_collection_store_id foreign key (store_id) references store
but when i try to use it with #ManyToMany association, it does not work as expected:
#ManyToMany
#JoinTable(name="collection_product",
joinColumns = {#JoinColumn(name="collection_id", referencedColumnName = "id")},
foreignKey = #ForeignKey(name = "fk_collection_product__collection_id"),
inverseJoinColumns = {#JoinColumn(name="product_id", referencedColumnName = "id")},
inverseForeignKey = #ForeignKey(name = "fk_collection_product__product_id"))
List<Product> products = new ArrayList<>();
the generated ddl does not honor my provided names, and revert to the auto generated random names:
alter table collection_product add constraint FK_skd8u4feadi59mpp8os1q1ar3 foreign key (product_id) references product
alter table collection_product add constraint FK_lbkv2n46sv06t6qfwabbk0wgw foreign key (collection_id) references collection
So, what is wrong here?
by the way, I tried to use foreignKey attribute on the #JoinColumn itself (it seems wrong, but i tried it anyway) and it does not help either:
#ManyToMany
#JoinTable(name="collection_product",
joinColumns={#JoinColumn(name="collection_id", referencedColumnName = "id",
foreignKey = #ForeignKey(name = "fk_collection_product__collection_id"))},
inverseJoinColumns={#JoinColumn(name="product_id", referencedColumnName = "id",
foreignKey = #ForeignKey(name = "fk_collection_product__product_id"))})
List<Product> products = new ArrayList<>();
it does not work either:
alter table collection_product add constraint FK_skd8u4feadi59mpp8os1q1ar3 foreign key (product_id) references product
alter table collection_product add constraint FK_lbkv2n46sv06t6qfwabbk0wgw foreign key (collection_id) references collection
what is the correct way to make this work?
Thanks
Searching the Hibernate issue tracker, I found several bug reports related to this issue.
It is partially fixed in the 5.x releases. some cases still not picked by the new systems, such as relationships in embedded persistent classes.
I intend to file a bug for this shortly
meanwhile you can upgrade to 5.x version, I use 5.1 and is working fine, and there is little porting issues.