Ryu
Ryu

Reputation: 113

JPA reference other entity in an entity constructor

In my database table Attribute, I will have a list of data loaded first. Every time, when I want to persist a new record of MyAttribute, I will need to search through the table Attribute first and select the appropriate record from table Attribute before I insert to table MyAttribute.

@Entity
class MyAttribute{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne(targetEntity = Attribute.class)
    @JoinColumn(name="attribute_id", referencedColumnName="id")
    Attribute detail;

    private String greet;

    public MyAttribute(){
        this.greet = "Hello World.";
        this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
    }

    //getter & setter
}

@Entity
class Attribute{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Index(name = "name_index")
    @Column(unique=true )
    private String name;

    //getter & setter
}

class MyDbLayer{
    private EntityManagerFactory emf;

    public MyDbLayer() {
        emf = Persistence.createEntityManagerFactory("MyPu");
    }

    public Attribute selectAttributeDetail(String name) {
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();

        Query queryGetAttribute = em.createQuery("select a from Attribute a where a.name = :attributeName");

        List<AttributeDescription> attributeDescList = queryGetAttribute.setParameter("attributeName", name).getResultList();

        AttributeDescription tempAttribute = null;

        if (!attributeDescList.isEmpty()) {
            tempAttribute = (AttributeDescription) attributeDescList.get(0);
        }

        em.clear();
        em.close();

        return tempAttribute;
    }
}

I'm not sure why I keep on receiving error like:

javax.persistence.PersistenceException: [PersistenceUnit: MyPu] Unable to build EntityManagerFactory

Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister

Caused by: org.hibernate.InstantiationException: could not instantiate test object

P.S. This is not the real code that I'm working on, but the structure is more or less the same.

Upvotes: 0

Views: 1580

Answers (2)

user3679868
user3679868

Reputation: 693

It is not in the JPA model to be able to access an EntityManager from an Entity. It can be done, but it can have different behaviors depending on the implementation.

In your case accessing an EntityManager from the no args constructor is never a good idea. Because thats the constructor used by the EntityManager when it loads an Entity. So every time MyAttribute is loaded by an EntityManager you will try to create antoher EntityManager to initialise the detail relationship which will be overwritten by the first EntityManager using the value it loaded from the database.

Usually you should have a service layer which has access to an EntityManager that manages your JPA Entities.

Upvotes: 0

Hank Lapidez
Hank Lapidez

Reputation: 2025

What about making a second construtor for MyAttribute?

public MyAttribute(){
    this.greet = "Hello World.";
    // this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
}

public MyAttribute(Attribute detail){
    this.greet = "Hello World.";
    this.detail = detail;
}

The default constructor is also used by jpa to load persited objects. this can cause unexpected behaviour

Upvotes: 3

Related Questions