Note that there are some explanatory texts on larger screens.

plurals
  1. POJPA 2.0 retrieve entity by business key
    primarykey
    data
    text
    <p>I know there have been a number of <em>similar</em> posts about this, but I couldn't find a clear answer to my problem.</p> <p>To make it as simple as possible, say I have such an entity:</p> <pre><code>@Entity public class Person implements Serializable { @Id private Long id; // PK private String name; // business key /* getters and setters */ /* override equals() and hashCode() to use the **name** field */ } </code></pre> <p>So, <code>id</code> is the PK and <code>name</code> is the business key. Say that I get a list of names, with possible duplicates, which I want to store. If I simply create one object per name, and let JPA make it persistent, my final table will contain duplicate names - Not acceptable.</p> <p>My question is what you think is the best approach, considering the alternatives I describe here below and (especially welcome) your own.</p> <h2>Possible solution 1: check the entity manager</h2> <p>Before creating a new person object, check if one with the same person name is already managed. <strong>Problem:</strong> The entity manager can only be queried by PK. IS there any workaround Idon't know about?</p> <h2>Possible solution 2: find objects by query</h2> <pre><code>Query query = em.createQuery("SELECT p FROM Person p WHERE p.name = ..."); List&lt;Person&gt; list = query.getResultList(); </code></pre> <p><strong>Questions:</strong> Should the objects requested be already loaded in the em, will this still fetch from database? If so, I suppose it would still be not very efficient if done very frequently, due to parsing the query?</p> <h2>Possible solution 3: keep a separate dictionary</h2> <p>This is possible because equals() and hashCode() are overridden to use the field <code>name</code>.</p> <pre><code>Map&lt;String,Person&gt; personDict = new HashMap&lt;String,Person&gt;(); for(String n : incomingNames) { Person p = personDict.get(n); if (p == null) { p = new Person(); p.setName(n); em.persist(p); personDict.put(n,p); } // do something with it } </code></pre> <p><strong>Problem 1:</strong> Wasting memory for large collections, as this is essentially what the entity manager does (not quite though!)</p> <p><strong>Problem 2:</strong> Suppose that I have a more complex schema, and that after the initial writing my application gets closed, started again, and needs to re-load the database. If all tables are loaded explicitly into the em, then I can easily re-populate the dictionaries (one per entity), but if I use lazy fetch and/or cascade read, then it's not so easy.</p> <p>I started recently with JPA (I use EclipseLink), so perhaps I am missing something fundamental here, because this issue seems to boil down to a very common usage pattern. </p> <p>Please enlighten me! </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload