Atmocreations
Atmocreations

Reputation: 10071

JPA more instances than desired

I have a class called NodeType backed using JPA by a SQL Server database.

Nothing special there, no relations, just some fields. There are even more of them, but for simplification I've omit them:

@Entity
@Table(name="node_type")
@NamedQuery(name="NodeType.findAll", query="SELECT n FROM NodeType n")
public class NodeType implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    private String name;

    public NodeType() {
    }

    public int getId() {
            return this.id;
    }

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

    public String getName() {
            return this.name;
    }

    public void setName(String name) {
            this.name = name;
    }

}

When starting up my application, I read them and put them all into a HashMap, taking the property name as key to find it easier later.

In the database, there are currently five items.

id  name       maxNoExits  mandatoryExits  defaultExits
==  =========  ==========  ==============  ============
1   NTYPE_HUP  0           NodeHangup
2   NTYPE_ANN  1           NodeAnnounce
3   NTYPE_SLP  1           NodeWait
4   NTYPE_XFR  0           NodeTransfer
5   NTYPE_TBR  32          NodeTimebased

Somewhen later, and I don't know where exactly this happens, multiple instances for each item suddenly exist (3 instances per item currently)

Example: In the application, I have an instance of NodeType with the values

1   NTYPE_HUP  0           NodeHangup

The eclipse debugger tells me that:

The last point shocks me as I'm not instanciating them anywhere in my application! Does anybody know when this happens?

If JPA uses a cache (does it?), it should look previously created items up using the @Id column. Even though I'm doing more than one createQuery, they should all refer to the same items. Or am I wrong?

It's all quite strange for me and I don't know how to debug it.

I hope someone can bring some light in the dark.

Edit: All I can tell is that these 15 instances exist as soon as I use the corresponding JPA request for the first time. Placing a debugger trap in the constructor, I can confirm that all instances are created right one after the other.

Edit2: For the fun and the sake of testing, I just tried to work it around reimplementing hashCode() (simply return this.id;) and overriding equals() (return this.id == other.id;)

The 15 instances are still there. As I'm only reading, I currently don't care about it as I can now consider all the three instances as an equal item. But it's not the solution to the base problem. I suspect this might happen elsewhere, too - without having tested.

Upvotes: 4

Views: 96

Answers (1)

bdulac
bdulac

Reputation: 1666

If I understand well, you have 5 tuples in the database, 5 different instances in the map (given that the names are uniques ?) and 15 different instances loaded by JPA, which are equals by groups of 3...

I guess this is a problem of Cache Level.

It is possible that EclipseLink creates different equal instances for a same tuple while reading if the loaded instances are stored in the Persistence Context Cache - Level 2 (i.e. the EntityManager) - and not the Persistence Unit Cache - Level 1 (i.e. the EntityManagerFactory) . You probably use a different EntityManager for each read operation. In such a case, EclipseLink can not find the previously cached entity.

This depends on your application configuration. The problem could also be caused by a memory lack and a weak reference cache. Further explanation is available in the EclipseLink cache documentations page.

Upvotes: 1

Related Questions