views:

248

answers:

3

Hi all,

I need to create a relation in Hibernate, linking three tables: Survey, User and Group. The Survey can be visible to a User or to a Group, and a Group is form of several Users.

My idea was to create a superclass for User and Group, and create a ManyToMany relationship between that superclass and Survey.

My problem is that Group, is not map to a table, but to a view, so I can't split the fields of Group among several tables -which would happen if I created a common superclass-.

I thought about creating a common interface, but mapping to them is not allowed. I will probably end up going for a two relations solution (Survey-User and Survey-Group), but I don't like too much that approach.

I thought as well about creating a table that would look like:

  Survey Id  |  ElementId  | Type

ElementId would be the Group or UserId, and the type... the type of it. Does anyone know how to achieve it using hibernate annotations? Any other ideas?

Thanks a lot

A: 

You can use the table per concrete class inheritance strategy, hibernate will replicate all properties for each subclass, this will work with a view.

I would also suggest the composite pattern for users/groups (which is close to your first option).

http://en.wikipedia.org/wiki/Composite_pattern

shipmaster
As far as I see it, it seems that approach won't work as since u don't have control over the view, two rows (one in Group and another in User) could happen to have the same id, hence there is no way to guarantee the uniqueness of the ids. With this approach the id has to be shared across several tables what is not possible with views (it might be got from a table in another schema that u don't have control over). How would u relate the Survey with the Element??
Juan Carlos Blanco Martínez
@Juan This is something the OP has to clarify. If you really have no control over the view in the sense that you are also not responsible for writing the entities and thus cannot guarantee id uniqueness, you can still use table per concrete class by mapping the id to a surrogate logical key that you know is unique (e.g. Group/User name).
shipmaster
That could be a good approach, the problem is that there is existent data in the tables and the model its based on the pre-existing keys, if I changed them everything would break :S
Jesus Benito
@Jesus If you dont have control on either the view or the java bean model that maps the view I dont see any other solution than the one you mentioned.
shipmaster
Yes, probably I was overthinking, I dont have many choices so I will have to go for that solution even if I dont like it too much..Thanks a lot!
Jesus Benito
A: 

This is possible. Such an 'inherited properties' approach can be achieved by defining the superclass as a MappedSuperclass.

EDIT:

There is also some alternatives listed in section 2.2.4 in the hibernate annotations reference doc, section 2.2.4.4 covers MappedSuperclass.

disown
A: 

I posted a very similar answer yesterday. To summarize, you can't use a mapped superclass because a mapped superclass is not an entity and can't be part of an association (which is what you want) but you can use an abstract Entity with a TABLE_PER_CLASS inheritance strategy to obtain a similar result.

Something like this (not tested):

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEntity {
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    @ManyToMany(mappedBy="entities")
    private Set<Survey> surveys = new HashSet<Survey>();
    ...

}

@Entity
public class User extends AbstractEntity {
    ...
}

@Entity
public class Group extends AbstractEntity {
    ...
}

@Entity
public class Survey {
    @Id @GeneratedValue
    private Long id;

    @ManyToMany
    private Set<AbstractEntity> entities = new HashSet<AbstractEntity>();

    ...
}

References

Pascal Thivent
As far as I see it, it seems that approach won't work as since u don't have control over the view, two rows (one in Group and another in User) could happen to have the same id, hence there is no way to guarantee the uniqueness of the ids. With this approach the id has to be shared across several tables what is not possible with views (it might be got from a table in another schema that u don't have control over). How would u relate the Survey with the Element??
Juan Carlos Blanco Martínez
@Juan Indeed but I expect a join to be possible on the view (maybe the OP should clarify this). I'll think about this.
Pascal Thivent
Juan Carlos is right, I don't have control at all over the view. And there is something more that I forgot to mention: the tables are already populated, so if I changed the model, I would have to create and run some db scripts to update the data, if possible I would like to avoid it.Because of it I mentioned the Survey Id | Element Id | Type approach. If a discriminator value(Type) is added to the ManyToMany relationship, my problem would be solved. But couldn't find a way of doing it
Jesus Benito