DAO(データ・アクセス・オブジェクト)
エンティティ作成
アノテーションを使い、JAVAとテーブル構造をマッピングしたものとなります。 一般的にパッケージ『entity』で管理するので、あらかじめ作成しておきましょう。
・『テーブル選択』画面がPOPしますので、[接続]アイコンをクリックします。
・すると唯一作成した『users』が表示されるのでチェックし「次へ」押下
・更に「次へ」押下
・『デフォルトのカスタマイズ』画面となるので以下を設定します。
・パッケージ:entity ・『完了』押下
<class>entity.User</class>
※JAVAの命名規則として単数形になるっぽいです
テーブルに『AUTO_INCREMENT』属性がある場合、エンティティには反映されません。
色々と不具合の温床となるので、以下の様にアノテーションを付与しましょう。
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
DAOを作成し、DBアクセスする
MVCフレームワークにおける『モデル』の要的存在となり、データベース操作を担当します。
一般的に使われるパッケージ名は、そのまま『dao』です。 まずは共通の基底クラスを作成します。
ファイル名名を『dao/BaseDao.java』で作成します。
package dao;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
public abstract class BaseDao<T, ID> implements Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName = "myMysqlUnit")
protected EntityManager em;
private final Class<T> entityClass;
public BaseDao(Class<T> entityClass) {
this.entityClass = entityClass;
}
// 保存
public void create(T entity) {
em.persist(entity);
}
// 主キーによる検索
public Optional<T> findById(ID id) {
return Optional.ofNullable(em.find(entityClass, id));
}
// 全件検索
public List<T> findAll() {
String jpql = "SELECT e FROM " + entityClass.getSimpleName() + " e";
return em.createQuery(jpql, entityClass).getResultList();
}
// 更新
public T update(T entity) {
return em.merge(entity);
}
// 削除
public void delete(T entity) {
em.remove(em.contains(entity) ? entity : em.merge(entity));
}
// IDによる削除
public void deleteById(ID id) {
findById(id).ifPresent(this::delete);
}
}
クラス『EntityManager』がDBを制御する実態となります。
『@PersistenceContext(unitName = "myMysqlUnit")』に注目して下さい。
《myMysqlUnit》は『persistence.xml』で設定した名前となり、このマッピングにより最終的なWildflyが管理するデータソースと連携できます。
先ほど作成した『User』クラスのDAOを作成するので、ファイル名は当然『UserDao.jva』となります。
作成したら以下の様に修正します。
package dao;
import java.util.List;
import entity.User;
import jakarta.enterprise.context.Dependent;
@Dependent
public class UserDao extends BaseDao<User, Integer> {
private static final long serialVersionUID = 1L;
public UserDao() {
super(User.class);
}
// 独自の検索クエリ
public List<User> findByName(String name) {
return em.createQuery(
"SELECT u FROM User u WHERE u.name = :name", User.class)
.setParameter("name", name).getResultList();
}
}
継承する『BaseDao』に連携するジェネリクスの2つ目は『Integer』としています。
これは1つ目の『User』クラスの主キーの型を指定する必要があります。
『SampleBean.java』のコンストラクタを以下の様に修正します。
@Inject
private UserDao dao;
~ 省略 ~
@Override
protected void initialize() {
dto.setName("");
dto.setMemo("");
List<User> users = dao.findByName("hoge太郎");
System.out.println("----------------------------");
for (User user : users) {
String hoge = user.getName();
System.out.println(hoge);
}
System.out.println("----------------------------");
}
エクリプスのコンソールに注目です。
...。
21:46:17,608 INFO [stdout] (default task-1) ----------------------------
21:46:17,821 INFO [stdout] (default task-1) ----------------------------
それもそのハズ。テーブルにデータがありません。
では手動で以下の情報を登録してみましょう。
insert into users (mail, pass, name) values ('foo@hoge.com', 'foo0000', 'foo太郎');
今度は『hoge太郎』とコンソールに表示されるハズです。
DAO具象クラスについて
※ C=Create、R=Read(select)、U=Update、D=Delete
でも個別のDAOでは何かと複雑なSQLを作成する要件が発生しがちですよね。 常に思ってる事なのですが、様々なフレームワークにはSQLを扱う『仕組み』が用意されています。
でもそれって、複雑なSQLだと無力ですよね(JOIN..EXISTS..など)。
何が言いたいかと言うと、
『結局平文が一番強い!』です。 先ほど作成した『UserDao』の、関数「findByName」を覚えていますか?
その中の以下文字列
"SELECT u FROM User u WHERE u.name = :name" これ平文じゃありませんよ。
テーブル名は『users』でしたね。上記はクラス名です!
平文のSQLで記述する場合は以下の様に修正する必要があります。
@SuppressWarnings("unchecked")
public List<User> findByName(String name) {
final String sql = "SELECT * FROM users WHERE name = :name";
return em.createNativeQuery(sql, User.class).setParameter("name", name).getResultList();
}
かなりウザいので『@SuppressWarnings("unchecked")』を付与して警告を非表示にしています。





クラス名がエラーになっている場合。
ビルドが通る場合は、エクリプスの不具合ですので、以下の方法でチェックを無効にします。まずその状態でビルドが通るか確認して下さい。
仮にビルドが通らない場合はガチのエラーですので、設定を見直しましょう。
※データソース名の大文字小文字等
・左メニュー > JPA > エラー/警告
・「プロジェクト固有の設定を可能にする」にチェックを入れる
・「永続化単位」のアコーディオンを展開する
・「persistence.xml ファイルにリストされているが注釈されていないクラス」を警告にする
・「適用」「適用して閉じる」押下