2016-06-13 12 views
0

できるだけ単純なエンティティを使用して、作成、編集、削除操作をどのように管理すればよいですか?例えばJPAデータベースからエンティティを作成、編集、削除する

ユーザー:

public class User { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    // Item can't exist without user 
    @OneToMany(cascade=CascadeType.ALL,mappedBy = "user",orphanRemoval=true) 
    private Set<Item> items = new HashSet<Item>(); 

    public Set<Item> getItems() { return items; } 

    public void addItem(Item item) { 
     items.add(item); 
    } 

    public void removeItem(Item item) { 
     if(!items.contains(item)) return; 
     items.remove(item); 
    } 

    // Group can exist without a user 
    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},mappedBy="users") 
    private Set<Group> groups = new HashSet<Group>(); 

    public Set<Group> getGroups() { return groups; } 

    public void setGroups(Set<Group> groups) { this.groups = groups; } 

    public void addGroup(Group group) { 
     groups.add(group); 
    } 

    publi void removeGroup(Group group) { 
     if(!groups.contains(group)) return; 
     groups.remove(group); 
    } 

    ... 
} 

グループ:

@Entity 
public class Group { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinTable(name = "GroupToUser", joinColumns = 
    @JoinColumn(name = "GroupId", referencedColumnName="Id"), inverseJoinColumns = 
    @JoinColumn(name = "UserId", referencedColumnName="Id")) 
    private Set<User> users = new HashSet<User>(); 

    public Set<User> getUsers() { return users; } 

    public void setUsers(Set<User> users) { this.users = users; } 

    public void addUser(User user) { 
     user.addGroup(this); 
    } 

    publi void removeUser(User user) { 
     if(!users.contains(user)) return; 
     users.remove(user); 
    } 

    ... 
} 

アイテム:

@Entity 
public class Item { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    private String name; 

    ... 

    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinColumn(name="UserId") 
    private User user; 

    public Set<User> getUser() { return user; } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    publi void removeUser() { 
     this.user = null; 
    } 

    ... 
} 

私は右のJPAのアノテーションを使用していますか?

ここに何を書きますか?

EntityManager em = getEntityManager(); 
em.getTransaction().begin(); 
??? 
em.getTransaction().commit(); 

削除/作成/編集操作のem.remove/persist/mergeメソッドを呼び出すだけでいいですか?

これらの操作ではいつjavax.persistence.EntityManager.getReferenceメソッドを使用する必要がありますか?

+0

JPAエンティティを管理するためにEntityManagerインスタンスが使用されることは理解しているようです。あなたはそれを試してみましたか? – scottb

答えて

0

Find()は、永続コンテキストのキャッシュからエンティティを配信します。存在しない場合は、データベースからロードされます。

GetReference()はエンティティをすぐにロードしません。プロキシ(特定のオブジェクト、実際のエンティティを読み込むための豊富なメソッドを持ついわゆる "代理")が返されます。だから、LazyLoadingの助けを借りて実現しています。

プロキシまたはその他の永続性メソッドの属性が必要/呼び出された場合にのみ、プロキシが対話し、データベースから実際のエンティティを読み込みます。

例:

User us = em.find(User.class, 70992); 

GetReference()が同様に使用されています。

User us = em.getReference(User.class, 70922); 

ユーザIDのエンティティが永続コンテキストでは知られていない場合、EntityNotFoundException()がスローされます。

データベースの状態にアクセスする必要がないときは、通常getReferenceメソッドを使用します(これはgetterメソッドを意味します)。状態を変更するだけです(私はセッターメソッドを意味します)。上記の場合

私は、ユーザーを取得した後、以下のような利用者の年齢を更新する場合:

setAge(age); 

私はfindメソッドを呼び出した場合、JPAプロバイダは、舞台裏、

SELECT NAME, AGE FROM USER WHERE USER_ID = ? 

UPDATE USER SET AGE = ? WHERE USER_ID = ? 

を呼び出します私がgetReferenceメソッドを呼び出すと、背後にあるJPAプロバイダが呼び出します。

UPDATE PERSON SET AGE = ? WHERE USER_ID = ? 

いつgetReferenceを呼び出すと、プロキシオブジェクトが取得されます。我々は、削除持続し、あなたのようにマージ使用する必要があり、残りについては

0

は個人的に私はRepository Software PatternSingle Responsability Principleについて読んでお勧めと述べています。

私の考えは、例えば、UserRepositoryを作成し、コントローラのような別のクラスは、必要なオブジェクトを作成して永続化しようとした後にそのリポジトリに移動することです。

は次のように動作するはずです:あなたがやったよう

まずpersist()エンティティにしようとし、その後、エンティティマネージャおよびトランザクションを取得します。 persist()メソッドがエンティティが永続性にあることを検出すると、PersistenceExceptionがスローされます。それをキャッチし、新しい取引を取得し、merge()メソッドを呼び出します。

+0

新しいものかどうかわからない場合は、単にmergeを使用してJPAに挿入または更新を処理させてみませんか? – Chris

0

最も簡単な方法は最良の方法ではありません。最高の最も簡単な方法は、私は(あなたがより良いJPQL namedQueries/orm.xmlについての詳細を読むが、更新アクションについて)考えて、このいずれかになります。

@WebFilter("*.htm") 
public class JPAFilter implements Filter { 
    private static final EntityManagerFactory entityManagerFactory 
     = Persistence.createEntityManagerFactory(/* yourprojectname */); 
    private static final ThreadLocal<EntityManager> entityManagers 
     = new ThreadLocal<>(); 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException {} 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) throws IOException, ServletException { 
      entityManagers.set(entityManagerFactory.createEntityManager()); 
     EntityManager entityManager = entityManagers.get(); 
     try { 
      request.setCharacterEncoding("UTF-8"); 
      chain.doFilter(request, response); 
     } finally { 
      if (entityManager.getTransaction().isActive()) { 
       entityManager.getTransaction().rollback(); 
      } 
      entityManager.close(); 
      entityManagers.remove(); 
     } 
    } 

    public static EntityManager getEntityManager() { 
     return entityManagers.get(); 
    } 

    @Override 
    public void destroy() { 
     entityManagerFactory.close(); 
    } 
} 

---- 

abstract class AbstractDAO { 
    protected EntityManager getEntityManager() { 
     return JPAFilter.getEntityManager() 
    } 
} 

---- 

public class UserDAO extends AbstractDAO { 
    public void create(User user) { 
     getEntityManager().persist(user); 
    } 

    public User read(long id) { 
     return getEntityManager().find(User.class, id); 
    } 

    public void delete(long id) { 
     if (user != null) { 
      getEntityManager().remove(user); 
     } 
    } 
} 

---- 

abstract class AbstractService { 
    private EntityManager getEntityManager() { 
     return JPAFilter.getEntityManager(); 
    } 

    protected void beginTransaction() { 
     getEntityManager().getTransaction().begin(); 
    } 

    protected void commit() { 
     getEntityManager().getTransaction().commit(); 
    } 

    protected void rollback() { 
     getEntityManager().getTransaction().rollback(); 
    } 
} 

---- 

public class UserService extends AbstractService { 
    private final UserDAO userDAO = new UserDAO(); 

    public void create(User user) { 
     beginTransaction(); 
     userDAO.create(user); 
     commit(); 
    } 

    public User read(long id) { 
     return userDAO.read(id) 
    } 

    public void delete(long id) { 
     userDAO.delete(id); 
    } 
} 

---- 

@WebServlet("/users.htm") 
public class ManageUsersServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
    private static final String VIEW = "/WEB-INF/JSP/users.jsp"; 
    private final transient UserService userService = new UserService(); 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     // here you do whatever you want using your userService methods. 
    } 
} 

P.S.更新時にデータベースからレコードをロックすることを忘れないでください(悲観的ロックまたは楽観的ロック例外の捕捉を使用)。

「CRA Operations with JPA」を検索すると、それについての情報がたくさん見つかります。私が見つけた最初のチュートリアルはこれです:http://www.objectdb.com/java/jpa/persistence/crud

0

私はjpaアノテーションを正しく使用していますか?一見

あなたがシリアライズ可能な分離レベルを使用しない限り、私は(EntityManagerのは、失われたアップデートに対して標準の安全装置であるオプティミスティックロックを実行するために必要な@Versionフィールド、存在しないことを質問したいです多くのデータベースシステムで特別な構成が必要になります)。

削除/作成/編集操作のem.remove/persist/mergeメソッドを呼び出すだけでいいですか?

これは、最も簡単で通常は最良の方法です。

これらの操作では、いつjavax.persistence.EntityManager.getReferenceメソッドを使用する必要がありますか?

getReferenceは、データベースからデータをロードせずにエンティティを参照する場合に便利です。たとえば、あなたが持っている可能性があり:

public void updateUser(Item item, int userId) { 
    item.setUser(entityManager.getReference(User.class, userId)); // does not require a query 
    entityManager.merge(item); 
} 

取引

をあなたは例外がスローされた場合、トランザクションをロールバックしたいとあなたは、両方の場合には(それが終わったら、EntityManagerを閉じます成功と失敗の)

関連するノートでは、アプリケーションが非常に小さい場合は、宣言型トランザクション管理を調べて、すべての操作にコードを記述する必要はありません。たとえば、Springで@Transactionalをクラスに注釈を付けて、メソッドが呼び出されるたびにSpringがトランザクションを開始(および終了)できるようにすることができます。

関連する問題