JPA and selective ManyToOne relationship - jpa

Sure this is a simple answer, but I cannot find the right source to give the details.
I have a ManyToOne relationship. Because of a synchronization system, when a child is removed a field named 'removed' is set to 'true', and will automatically be deleted only a month later.
However, in the meanwhile, I would like it not to appear in the List in the parent. Is there an easy way to specify a select statement in the definition of the field or so?
#OneToMany(mappedBy = "parent")
#OrderBy("level")
public List<MenuItem> children;

As you are using hibernate you can use the #where annotation. I never used it myself but it seems quite straight forward. Have a look here: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection

Related

Automatic reindex of #IndexedEmbedded field

As far I can understand from reading this part of the documentation of
https://docs.jboss.org/hibernate/search/6.0/reference/en-US/html_single/#mapper-orm-reindexing-basics
there's no automatic reindexing on #IndexedEmbedded fields that doesn't have a bidirectional mapping. Am I correct? And if so I'm curious to know what leaded to introduce this, because in Hibernate search automatic reindexing happened when updating a field in an #IndexedEmbedded field. Does this mean that now I'm responsible to update the index?
Here's an example of my use case which leads to a not updated index:
#Indexed(index = "foo_index")
#Entity
public class Foo {
private Long id;
#IndexedEmbedded
#ManyToOne(fetch = LAZY)
private Bar bar;
}
#Entity
public class Bar {
private Long id;
#GenericField
private String barFieldOne;
#GenericField
private String barFieldTwo;
}
Then let's say I retrieve the Foo from the db and change a bar field like this:
Foo foo = repository.findById(1);
foo.getBar().setBarFieldOne("newValue");
repository.save(foo);
This will not trigger index update of the foo index despite I'm working through the #Indexed object(Foo in our case). I have a lot of uni directional relations and I don't want to make them bidirectional because I don't need them and they can lead to performance problems. I understand that if I update the bar entity by itself it won't update the index but here I'm updating it through the main #Indexed entity and I expect the index to be updated.
This use case worked flawlessly in hibernate search 5 and in my honest opinion this is an important. Is there a way to make it work here, because this will make my life a lot easier.
You understood well, Hibernate Search cannot trigger reindexing when there's just an unidirectional association between the modified entity and the indexed entity.
There are plans to address that, maybe, one day, but that will still require some configuration: https://hibernate.atlassian.net/browse/HSEARCH-1937
This use case worked flawlessly in hibernate search 5 and in my honest opinion this is an important
I'm going to need a reproducer for that. I would be very, very surprised if you managed to make it work. If it worked, it was probably just a side-effect of something else: you disabled dirty checking, or you had a transient property on your entity that caused it to be reindexed every single time.
All we did in Search 6 was to make sure we throw an error when you try to use #IndexedEmbedded on an uni-directional association, and force you to explicitly disable automatic reindexing for that association.
It didn't work in Hibernate Search 5 either, but Hibernate Search 5 would ignore these problems silently and you would end up thinking it worked, but it did not.
So really, the only change is that you are now aware of the problem. It existed before.

JPA ManyToMany relationship -- Why would association (join) table be empty

I have two entities Account and Position. The POSITION table and the ACCOUNT table have contents but the POSITION_ACCOUNT table, which I think should have at least one row, is empty. What could I be doing wrong? Here is the relevant code (I am using EclipseLink 2.4.2:
In Position:
#ManyToMany
private List accounts;
In Account:
#ManyToMany(mappedBy = "accounts",fetch=FetchType.EAGER,cascade=CascadeType.PERSIST)
#JoinTable(name="POSITION_ACCOUNT")
Confusing to me and perhaps relevant is that some examples I see annotate the getters and setters but others, as I am doing here, annotate the actual Lists.
It turns out that I needed to specify cascade=CascadeType.PERSIST on both sides of the relationship but there were other application-specific issues along the way. I don't know if reading the original question or this answer will be of much help to anyone. Sorry.

JPA ManyToMany filter on link table

We have a many to many relation with let's say Entity1 and Entity2.
Now when we delete an element of Entity2, we don't in fact remove it from database but simply have a field "isActive" which we set to false.
When that happens, we would like however to remove all relations between any element of Entity1 to the element of Entity2 which was "deleted".
In SQL this transforms to a entity1 table, entity2 table, and entity1TOentity2 table. In SQL we can simply do a single update,
delete from entity1TOentity2 where entity2ID = :entity2Id
In JPA, we could load all elements of Entity1 as objects, with a join fetch on the relation, then remove one by one in Java the connections, but it's terribly wasteful...
Is there any way to formulate that SQL query with JPAQL?
I know it's possible to explicitly define a link entity, and make JPA use it, then I guess I could run a query basically identical to the SQL one on that link entity, but it seems a bit overkill.
am I missing a solution as nice as the raw SQL, but using the JPA API/JPAQL?
Given your context, I see only one option: native queries.
On pure JPA, I don't know a clean way to do it.
If you're using Hibernate behind the scenes, there is a high-level solution:
#Entity
#Where(clause='isActive=true')
public class Entity2{
}

Composite key with JPA entity, implementing tree of objects in one table?

I have one table named PLACES with one composite primary key (parent_id, version_id). It is a tree of objects, which are linked through the keys. One child has just one parent, and one parent may have many children.
How can I describe it with JPA entity?
Use a ManyToOne relation from the child to the parent.
This is for OpenJpa. Might even work.
public class Place{
#EmbeddedId
PlaceId id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="PARENT_ID" referencedColumnName="ID"), // ID = matching primary key
#JoinColumn(name="PARENT_VER" referencedColumnName="VER") //etc
})
public Place parent;
#OneToMany(fetch=FetchType.LAZY, mappedBy="parent")
public List<Place> childPlaces;
}
The OneToMany relation might be omitted if it's not needed. If I remember correctly, it needs to be managed, ie childs need to be inserted there too when creating child-places, by you, using java.
Btw.
I would advise against using a version column in a composite key in order to manually keep old versions of your data (for auditing or similar purposes) as that slows down and complicates all joins, and generally will make you miserable at some point in your life - As opposed to using a version column that is not part of a composite key, used for optimistic locking.
You might want to look into some kind of build in support for auditing/logging. OpenJpa has auditing support (OpenJPA Audit) and most database provide some support, either out-of-the-box or by using triggers. All alternatives are faster and better than using composite keys.

Envers generating "add"+"delete" edits instead of "modify" for Map<>

I have a field declared as a Map<MyEnum, String>, which is audited. When a change is made to one of the elements in the map, envers is generated two edits, an ADD and a DEL, rather that a single MOD, which in turn means a constraint violation when trying to insert into the audit table, since there are two edits for a single field in a single entity in the same revision.
I'm guessing I could probably work around the problem by making revision_type part of the table's key (which would permit one edit of each type per field per entity), but that seems like an ugly hack, besides the fact that I lose track of which happened first, and the fact that it's just wrong.
The field is being persisted properly, by the way... it's just the audit records that fail.
The field's declaration:
#ElementCollection
#CollectionTable(name = "configuration_property", joinColumns = #JoinColumn(name = "configuration_id"))
#MapKeyColumn(name = "property_name")
#Column(name = "property_value", columnDefinition = "longtext")
#MapKeyEnumerated(EnumType.STRING)
private Map<ConfigurationProperty, String> properties = new EnumMap<ConfigurationProperty, String>(ConfigurationProperty.class);
I'm using Hibernate v3.5.6.
I haven't been able to find any bug reports regarding this, so I'm thinking I'm doing something wrong... any ideas?
If you look at AbstractCollectionMapper.mapCollectionChanges, the current implementation only does additions and removals. I think the map is viewed as a collection of tuples: (key, value), so there are never any modifications. The bug is then in the schema generation, which should generate the keys properly. Please file a JIRA bug - https://hibernate.onjira.com, Envers component.