Update UniqueConstrains on a JPA table - java

I have a table defined as follow:
#Entity
#Table(
uniqueConstraints = {#UniqueConstraint(columnNames = {"reward_id", "transaction_id"})}
)
public class ShipmentItem extends Model {
...
}
I want to change the unique constraint to make it more relaxed:
#Entity
#Table(
uniqueConstraints = {#UniqueConstraint(columnNames = {"reward_id", "transaction_id", "sku"})}
)
public class ShipmentItem extends Model {
...
}
The updated code compiles, but JPA doesn't change the table schema. Is there a configuration setting I need to use?
If JPA cannot do this, what's the systematic approach to this problem? I can write migration, however, JPA generates the name for the constraint automatically, so it's not obvious how to drop the old constraint.
Not sure if it matters, but I am using hibernate and mysql.

Since you are using Hibernate, there is a property for automatically updating your schema: hibernate.hbm2ddl.auto with the value update
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html
(But be aware that it is not recommended to use it on Production)

Related

can't figure out how to audit for null value in not owned entity using hibernate envers

What my project have:
rsqlParser in order to parse complicated queries
Hibernate envers for audit purposes
Pretty stupid middle developer who don't know how to implement isNull rsql query
I have two Object with strict one-to-one relationship: object A which contains object B, and object B, which contains object A.
In RDS it's looks like object B has an object_a_id field
Object_A entity class
#Entity
#Getter
#Setter
#Audited
#NoArgsConstructor
public class Object_A {
#OneToOne(mappedBy = "object_a")
private Object_B object_b;
}
Object_B entity
#Entity
#Getter
#Setter
#Audited
#NoArgsConstructor
public class Object_B {
#OneToOne
#JoinColumn(
name = "object_a_id",
referencedColumnName = "id",
foreignKey = #ForeignKey(name = "object_b_object_a_fk")
)
private Object_A object_a;
Clearly you see that Object_B OWNS Object_A and when I try to perfom something simple like
return auditProperty.isNull();
I get
This type of relation (object_b) isn't supported and can't be used in queries
I guess I need somehow to make custom query where I add some object_b subselect beforehand but can't figure out how to write it.
You should probably create an issue in the issue tracker(https://hibernate.atlassian.net) with a test case(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java) that shows this limitation and ask for an improvement for this.
Usually, in ORM this is handled on the SQL level by introducing an exists subquery like:
where not exists (select 1 from object_b b where b.object_a_id = rootAlias.id)
Not sure how that works exactly in your case, but you could try to do something similar in your query.

Spring JPA does not detect deleted tables

I deleted my tables to let them be recreated by Spring JPA, but spring does not create them. Instead, I'm getting the following exception:
Unable to create unique key constraint (guild_id, setting_key) on table guild_setting: database column 'guild_id' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
I don't know why I get this error, but before I deleted the tables in the database, the column name was guild_id, so what JPA says is not right.
This is an excerpt of the Entity:
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames={"guild_id", "setting_key"}))
public class GuildSetting extends Setting {
#Column(nullable = false)
private long guildId;
The following properties are set with the spring.datasource properties:
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
If you don't want to use #Column(name="guild_id")
You should use #UniqueConstraint(columnNames={"guildId", ...}
The generated table will contain the (correct) column, named guild_id
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames={"guildId", "setting_key"}))
public class GuildSetting extends Setting {
#Column(nullable = false)
private long guildId;
Agreed, this looks like a bug...
Note: You did not mention you have problems with the setting_key unique constraint.
Do you use #Column(name="setting_key") or private String setting_key?

Hibernate Envers can't resolve audit table

I have a JPA entity which I want audited. I added Envers to my project, and added the #Audited annotation to the entities I need. Now, the changes are being logged in the audit tables, but I cannot retrieve them through the audit readers provided by Envers.
My entity is as follows.
#Entity
#Audited
#AuditTable(value = "blog_posts_AUD")
#Table(name = "blog_posts")
public class Post {
...
}
I'm trying to query the audit tables as follows.
AuditReader reader = AuditReaderFactory.get(entityManager);
List revisions = reader.getRevisions(Post.class, primaryKey);
This fails, because the SQL call contains a reference to a table called org.foo.bar.blog_posts_AUD, which obviously does not exist. It seems that Hibernate is not picking up the #AuditTable annotation (or the default audit table suffix, for that matter). Anyone ever faced this before?

Constrains on class name for hibernate query in java

Sorry if it is a stupid question but I don't know Java almost at all.
I have a table "Orders" in a postgreSQL database, which I access by Hibernate, mapping the table to a class:
#Entity
#Table(name = "Orders")
public class Orders { ... }
This works. However, if I change the class name to "Order", thus:
#Entity
#Table(name = "Orders")
public class Order { ... }
I get an error:
org.hibernate.hql.ast.QuerySyntaxException: Orders is not mapped [from Orders]
of course I have already updated the hibernate xml config file, switching from
<mapping class="<path>.orders.Orders"/>
to
<mapping class="<path>.orders.Order"/>
any idea why ? What am I missing ? The mapping between the DB table and the class is established only on the basis of the #table annotation and not on the class name, isn't it ?
You're missing the fact that JPQL is not SQL. It works on entity names and property/field names, not on table names and column names. Since you changes the name of the entity class from Orders to Order, you need to change your JPQL queries from
select o from Orders o ...
to
select o from Order o ...
The name of the table that the entity maps is completely irrelevant.

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.

Categories

Resources