Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping value objects from third party libraries

Tags:

hibernate

jpa

I have the following entity I need to persist to a relational DB via Hibernate annotations:

@Entity
@Table(name="fizzes")
public class Fizz {
    @Id @GeneratedValue
    @Column(name="fizz_id")
    private int id;

    @Column(name="fizz_wooz")
    private String wooz;

    // ??? here I am unsure!
    private Buzz buzz;

    // Constructor, getters/setters down here, etc...
}

public class Buzz {
    private int jupiter;

    private String neptune;

    // Constructor, getters/setters down here, etc...
}

The problem with Buzz is:

  • I do not want it to be its own entity/table. I want it to be a "value object/type" that gets mapped to the fizzes table (by way of adding columns to it)
  • Buzz is from a third party library and hence I can't modify it

Hence the final result, in table form, that I'm looking for is:

[fizzes] table
==============
fizz_id, PRIMARY KEY AUTO INCREMENT
fizz_wooz, NVARCHAR(50) NOT NULL
fizz_buzz_jupiter, INT NOT NULL
fizz_buzz_neptune, NVARCHAR(100) NOT NULL

How can I get Hibernate to do this annotation-based mapping when I can't modify Buzz?

like image 993
DirtyMikeAndTheBoys Avatar asked Oct 16 '15 06:10

DirtyMikeAndTheBoys


1 Answers

What you are searching for is called Embeddable.

@Entity
public class Fizz {
    ...

    @Embedded
    private Buzz buzz;

}

And you can define a mapping file just for Buzz:

<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm    
                        http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
    <embeddable class="...Buzz">
        <attributes>
            <basic name="jupiter"><column name="fizz_buzz_jupiter"/></basic>
            <basic name="neptune"><column name="fizz_buzz_neptune"/></basic>
        </attributes>
    </embeddable>
</entity-mappings>

You can include that mapping file in your persistence.xml:

<persistence-unit>
    <mapping-file>.../orm.xml</mapping-file>
</persistence-unit>

If you really want to use annotations for Buzz: You can't define annotations for other classes. Thats the meaning of annotations: they are inline and belong to their class. Otherwise there would be no benefit compared to mapping files...

But you could extend Buzz and use that one with property access:

@Entity
public class Fizz {
    ...

    @Embedded
    private BuzzExtension buzz;

}

@Embeddable
@Access(AccessType.PROPERTY)
public class BuzzExtension extends Buzz {
    @Column(name="fizz_buzz_jupiter")
    public int getJupiter() {
        return super.getJupiter();
    }

    @Column(name="fizz_buzz_neptune")
    public String getNeptune() {
        return super.getNeptune();
    }

}

Only drawback: You can't use instances of Buzz in Fizz.

like image 158
Tobias Liefke Avatar answered Sep 18 '22 11:09

Tobias Liefke