Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate extend entity for same table

Tags:

java

hibernate

I have a table with two fields I would like to have two objects.

First one only has field1

@Entity(name = "simpleTableObject")
@Table(name = "someTable")
public class SimpleTableObject
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    protected long id;

    @Column(name = "field1")
    private String field1;

Second one has all two fields

@Entity(name = "tableObject")
@Table(name = "someTable")
public class TableObject
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    protected long id;

    @Column(name = "field1")
    private String field1;

    @Column(name = "field2")
    private String field2;

I load each one using

@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List get(Class aClass)
{
    ClassMetadata hibernateMetadata = sessionFactory.getClassMetadata(aClass);
    if (hibernateMetadata == null)
    {
        return null;
    }
    if (hibernateMetadata instanceof AbstractEntityPersister)
    {
        AbstractEntityPersister persister = (AbstractEntityPersister) hibernateMetadata;
        String                  tableName = persister.getTableName();
        if (tableName != null)
        {
            return sessionFactory.getCurrentSession().
                    createQuery("from " + tableName).list();
        }
    }
    return null;
}

What I would like to do is have TableObject extend SimpleTableObject. How would I go about doing that?

like image 931
Quillion Avatar asked Mar 05 '17 14:03

Quillion


2 Answers

You can have a common superclass for both entities:

@MappedSuperclass
public abstract class AbstractTableObject {
 // common mappings
}

@Entity
@Table(name = "someTable")
public class TableObject extends AbstractTableObject {
 // remaining mappings
}

@Entity
@Table(name = "someTable")
@Immutable
public class SimpleTableObject extends AbstractTableObject {
 // nothing here
}

Additionally, you can mark the SimpleTableObject entity to be @Immutable as shown above, so that it cannot be persisted or updated accidentally.

like image 128
Dragan Bozanovic Avatar answered Sep 19 '22 03:09

Dragan Bozanovic


If you want save common fields in your required tables means suppose you have class A and B and you have some common filed like created_by,updated_by and you want to save field1,field2 in both entity: IN database level:

query> select * from A;
+----++------------------------+
| id | created_by | updated_by |
+----+------------+------------+
|  3 |    xyz     | abc        |
+----+------------+------------+
query> select * from B;
 +----++------------------------+
| id | created_by | updated_by |
+----+------------+------------+
|  3 |    xyz     | abc        |
+----+------------+------------+

for this type of structure you should use @MappedSuperclass as @Dragan Bozanovic suggested

But if you want Parent Child relation and want generate table per class then you can use @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) it will create table per class e.g: Suppose you have 2 class Payment and CreditCard, Payment is parent class for CreditCard.

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Payment {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    @Column(nullable = false)
    private double amount;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }
}


@Entity
public class CreditCard extends Payment {
private String ccNumber;
private Date expireDate;

    public String getCcNumber() {
        return ccNumber;
    }

    public void setCcNumber(String ccNumber) {
        this.ccNumber = ccNumber;
    }

    public Date getExpireDate() {
        return expireDate;
    }

    public void setExpireDate(Date expireDate) {
        this.expireDate = expireDate;
    }
}

Now you will save date :

public class TestConcreteClasses {
    public static void main(String[] args) {
        Payment payment = new Payment();
        payment.setAmount(52.6);
        createData(payment);
        CreditCard creditCard = new CreditCard();
        creditCard.setAmount(10);
        creditCard.setCcNumber("2536985474561236");
        creditCard.setExpireDate(new Date());
        createData(creditCard);

    }

    private static void createData(Payment instance) {
        Session session = HibernateUtil.getSession();
        session.beginTransaction();
        session.save(instance);
        session.getTransaction().commit();
    }
}

then data will save like

query> select * from Payment;
+----+--------+
| id | amount |
+----+--------+
|  1 |   52.6 |
+----+--------+
1 row in set (0.00 sec)

 select * from CreditCard;
+----+--------+------------------+---------------------+
| id | amount | ccNumber         | expireDate          |
+----+--------+------------------+---------------------+
|  2 |     10 | 2536985474561236 | 2017-03-12 14:10:15 |
+----+--------+------------------+---------------------+
1 row in set (0.00 sec)

There are 3 types of inheritance used in hibernate, here is hibernate doc for inheritance https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/InheritanceType.html, you should pick any of them according to your requirement.

like image 31
Bhushan Uniyal Avatar answered Sep 21 '22 03:09

Bhushan Uniyal