Hibernate Discriminator

1.9k views Asked by At

I have something like that

table ACTION
name
resource_type
resource_id

resource_type and resource_id are used to discriminate type of resource:

resource_type can be image or video, if resource_type contains image resource_id is id of the table IMAGE; if resource_type contains video resource_id is id of the table VIDEO

here IMAGE and VIDEO tables

table IMAGE (*)
id 
imageType

table VIDEO (*)
id
videoType

(*) tables are more complicated, but for better explanation I shrank it!!!

I have the following class, too

class Action{
    private Resource resource;
    //getter and setter
}

interface Resource{}

class Image implements Resource{
    private Integer id;
    private String imageType;
    //getter and setter
}

class Video implements Resource{
    private Integer id;
    private String videoType;
    //getter and setter
}

i tried to understand something about discriminator attribute from this tutorial: http://viralpatel.net/blogs/hibernate-inheritence-table-per-hierarchy-mapping/ but example is little bit diffenet...-_-'

I want map IMAGE end VIDEO table in Resource object of Action class,how I can map these pojo classes with hibernate xml mapper???

1

There are 1 answers

1
Sarah On

You don't need to use a discriminator. You can use inheritance using the "Table per class" approach. Here's what you do.

  1. Define class "Resource" that has "id" property which is an id.
  2. Define two subclasses, "Image" and "Video" that extend Resource and add additional properties - in your example, "imageType" and "videoType".
  3. Define class "Action" that has a @ManyToOne to Resource. If you want the "resourceType" property here as you described in your post, you can have it, but it's completely unnecessary to get things to work.
  4. I'm not sure what type of id generation (if any) you want or what type of cascading from Action to Resource, so for simplicity's sake I assumed none for both of these.

With this approach, you'll get 3 tables in the database.

Here's the shell of an implementation:

@Entity 
@Inheritance (strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Resource {

    @Id
    @Column(name="ID")
    private String id;

    public Resource() {}
    public Resource(String id)  { this.id = id;  }
    ... // getters and setters
}

@Entity

/* Table per Concrete Class */
@Table (name="Image") 
public class Image extends Resource {

    private String imageType;  // Other properties unique to Image

    public Image() {}
    public Image(String id) { super(id); }
    public Image(String id, ...) { super(id); .... // setters }
    ... // getters and setters
}

/* Table per Concrete Class */
@Table (name="Video") 
public class Video extends Resource {

    private String videoType;   // Other properties unique to Video
    public Video() {}
    public Video(String id) { super(id); }
    public Video(String id, ...) { super(id); .... // setters }
    ... // getters and setters
}

With this approach, the following unit test shows the desired behavior:

Image image = new Image("i1", "imageType");
Video video = new Video("v1", "videoType");

Action imageAction = new Action("imageAction", image, "image");
Action videoAction = new Action("videoAction", video, "video");

manager.persist(image);
manager.persist(video);
manager.persist(imageAction);
manager.persist(videoAction);
manager.getTransaction().commit();

...


manager.getTransaction().begin();

System.out.println("********** Actions and Resources");
List<Action> result1 = manager.createQuery( "from Action" ).getResultList();
for ( Action a : result1 ) {
    System.out.println(a);
}
manager.getTransaction().commit();

Implementing toString() for all of these classes, the following output is produced:

Hibernate: create table Action (NAME varchar(255) not null, RESOURCE_TYPE varchar(255), RESOURCE_ID varchar(255), primary key (NAME)) Hibernate: create table Image (ID varchar(255) not null, imageProperty varchar(255), primary key (ID)) Hibernate: create table Video (ID varchar(255) not null, videoProperty varchar(255), primary key (ID))

**** Actions and Resources Action( name=imageAction resource=Image( id=i1 imageType=imageType) resourceType=image) Action( name=videoAction resource=Video( id=v1 videoType=videoType) resourceType=video)

Hope this helps to answer your question.

Sarah