-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Replacing @Formula with a proper @ElementCollection mapping
PostPosted: Tue Aug 02, 2016 9:07 am 
Newbie

Joined: Tue Aug 02, 2016 7:51 am
Posts: 6
I've stumbled upon a situation i cannot resolve using Hibernate documentation - i cannot alter an @ElementCollection from within the corresponding entity or even the DAO/Service.
My setup has a hibernate entity, separated into two classes:

Code:
@Entity
@Table(name = "PERSON")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value="person")
public class Person implements PersonInterface{
    ...
    @ElementCollection
    @Formula("(SELECT groupId FROM PERSON_GROUPS WHERE id = id)")
    protected List<Integer> groups = new ArrayList<>();
    ...
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
    @JoinTable(name = "user_roles", joinColumns = {
        @JoinColumn(name = "USER_ID", nullable = false, updatable = false)},
        inverseJoinColumns = { @JoinColumn(name = "ROLE_ID", nullable = false, updatable = false)})
    protected List<Role> roles = new ArrayList<>();

Code:
@Entity
@DiscriminatorValue("mutableperson")
public class MutablePerson extends Person implements MutablePersonInterface{
    ...
    public void excludeFromRole(Integer roleId){
        roles.remove(roleId);
    }

    public void excludeFromGroup(Integer groupId){
        groups.remove(groupId);
    }
}

The thing is, while excludeFromRole works, excludeFromGroup throws an exception "failed to lazily initialize a collection of role". I thought that had something to do with no open sessions, etc., but even when i explicitly call excludeFromGroup in DAO with an entityManager, it still returns the same exception.
I tried detaching the entity with EntityManager or closing the session in which it was fetched from the DB, but it didn't help.
This page https://docs.jboss.org/hibernate/orm/5. ... rmula.html says, that Formula represents a read-only state. Does this mean what i'm trying to do is effectively impossible and i have to look at @ColumnTransformer (which i can't get to work properly so far)?


Top
 Profile  
 
 Post subject: Re: Altering @Formula annotated @ElementCollection
PostPosted: Tue Aug 02, 2016 9:38 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Just as you concluded, @Formula gives you a read-only mapping, so you cannot benefit from the very convenient dirty checking mechanism.

What you need to do is to replace @Formula with a proper @ElementCollection mapping. For this, the groups mapping becomes:

Code:
@ElementCollection
@CollectionTable(
    name="PERSON_GROUPS",
    joinColumns=@JoinColumn(name="id")
)
@Column(name="groupId")
protected List<Integer> groups = new ArrayList<>();


Top
 Profile  
 
 Post subject: Re: Replacing @Formula with a proper @ElementCollection mapping
PostPosted: Tue Aug 02, 2016 10:50 am 
Newbie

Joined: Tue Aug 02, 2016 7:51 am
Posts: 6
Ok, that seems to work in @Transactional context, thank you.

I don't understand, though, what's the difference between calling remove on those 2 fields:
Code:
    @ElementCollection
    @CollectionTable(
            name="PERSON_GROUPS",
            joinColumns=@JoinColumn(name="PERSON_USER_ID")
    )
    @Column(name="GROUP_ID")
    protected List<Integer> groups = new ArrayList<>();

   @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
   @JoinTable(name = "user_roles", joinColumns = {
         @JoinColumn(name = "USER_ID", nullable = false, updatable = false)},
         inverseJoinColumns = { @JoinColumn(name = "ROLE_ID", nullable = false, updatable = false)})
   protected List<Role> roles = new ArrayList<>();

Even though both are lazily accessed, Roles can be changed without any opened session, and Groups - not so much.
Is there a way to make something like this work, without the need to use DAO as a proxy?
Code:
MutablePerson personFromDb = (MutablePerson) personService.getMutablePersonById(0);
personFromDb.excludeFromGroup(0);


Top
 Profile  
 
 Post subject: Re: Replacing @Formula with a proper @ElementCollection mapping
PostPosted: Tue Aug 02, 2016 2:28 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
I think you're making a wrong observation. Typically, if you try to modify an entity outside of a Transaction, you get an exception.


Top
 Profile  
 
 Post subject: Re: Replacing @Formula with a proper @ElementCollection mapping
PostPosted: Wed Aug 03, 2016 4:40 am 
Newbie

Joined: Tue Aug 02, 2016 7:51 am
Posts: 6
Indeed, with all the modifications i've made to the DAO during my "investigations", i forgot that in getEntityById() i was initializing Roles with Hibernate.initialize(), which was the cause of difference in behaviour.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.