ITエンジニアぽむのブログ

IT系で気になったことを書き留めておく備忘録です。仕事でよく使っているJavaと自宅で使っているLinuxについて書いていこうと思っています。同じお悩みをお持ちの方のお役に立てたら嬉しいです。

Struts2でO/Rマッパを使って家電情報を編集してみよう!

こんにちは、ぽむです。

今回は、Struts2フレームワークを使ってO/Rマッパ経由で家電情報テーブルを編集するプログラムをご紹介したいと思います。

はじめに

前回までで、家電情報テーブルにデータを新規保存する方法を見てきました。

pom2019.hatenablog.com

今回は、Struts2を使って元あるテーブルのデータを編集する方法について見ていきたいと思います。

開発環境

開発環境は下記の通りです。

Struts22.5.14.1
Hibernate4.3.0.Final
MySQL8.0.16

ビューの作成

画面 編集モードの場合、編集するidが表示されます。

Javascript 編集モードの場合、フォームデータにidをセットして、更新用のアクションを呼び出しています。

※編集モードは、パラメータisNewにtrueがセットされているかどうかで判断しています。

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>家電情報の登録</title>
    <style>
    table {
        border-collapse: collapse;
    }
    td {
        border: 1px solid gray;
        padding: 3px 8px;
    }
    .grayStyle {
        background: lightgray;
    }
    </style>
    <%-- jQuery --%>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <%-- jQuery UI --%>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <%-- jQuery UI(日本語ライブラリ) --%>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
</head>
<body>
<h2>家電情報の登録</h2>

<p>
    <button id="btnBack">戻る</button>
    <button id="btnSave">保存</button>
</p>

<table>
    <tr>
        <td>id</td>
        <td id="id" class="grayStyle">
            <s:if test='"true".equals(isNew)'>
                idは自動採番されます。
            </s:if>
            <s:else>
                <s:property value="id"/>
            </s:else>
        </td>
    <tr>
        <td>家電名</td>
        <td><input id="householdAppliancesName" type="text" value="<s:property value='householdAppliancesName'/>"/></td>
    </tr>
    <tr>
        <td>購入日時</td>
        <td><input id="purchaseDate" type="text" value="<s:property value='purchaseDate'/>" readonly="readonly"/></td>
    </tr>
</table>

<%-- 隠しパラメータ --%>
<input id="isNew" type="hidden" value="<s:property value='isNew'/>">

<script>
   $(function() {
       //日付ピッカーの設定
       $('#purchaseDate').datepicker({
           dateFormat: 'yy/mm/dd',
           changeYear: true,
           changeMonth: true
       });
       
       //戻るボタン
       $('#btnBack').on('click', function() {
           history.back();
       });
       
       //保存ボタン
       $('#btnSave').on('click', function() {
           //フォームデータの取得
           var fd = new FormData();
           
           var url;
           var isNew = $('#isNew').val();
           if (isNew && isNew == "true") {
               //保存の場合
               url = '${pageContext.request.contextPath}/save';
           } else {
               //編集の場合
               fd.append("id", $('#id').html());
               url = '${pageContext.request.contextPath}/update';
           }
           
           //フォームデータの追加
           fd.append("householdAppliancesName", $('#householdAppliancesName').val());
           fd.append("purchaseDate", $('#purchaseDate').val());
           
           //AJAX通信
           $.ajax({
               url: url,
               type: 'POST',
               data: fd,
               processData: false,
               contentType: false
           })
           //Ajaxリクエストが成功した時発動
           .done( (data) => {
               location.href = "${pageContext.request.contextPath}/display";
           })
           //Ajaxリクエストが失敗した時発動
           .fail( (data) => {
           })
           //Ajaxリクエストが成功・失敗どちらでも発動
           .always( (data) => {
           });
       });
   });
</script>
</body>
</html>

モデルの作成

連携データの作成

編集するためにidを連携しないといけないため、モデルにidを追加しています。

package com.pom2019.Struts2Web.model;

import java.util.List;

import com.pom2019.Struts2Web.entities.HouseholdAppliances;

public class IndexModel {
    private List<HouseholdAppliances> list;
    //新規登録フラグ
    private String isNew;
    //登録用
    private String id;
    private String householdAppliancesName;
    private String purchaseDate;

    //ゲッター、セッター
    public List<HouseholdAppliances> getList() {
        return list;
    }
    public void setList(List<HouseholdAppliances> list) {
        this.list = list;
    }
    public String getIsNew() {
        return isNew;
    }
    public void setIsNew(String isNew) {
        this.isNew = isNew;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getHouseholdAppliancesName() {
        return householdAppliancesName;
    }
    public void setHouseholdAppliancesName(String householdAppliancesName) {
        this.householdAppliancesName = householdAppliancesName;
    }
    public String getPurchaseDate() {
        return purchaseDate;
    }
    public void setPurchaseDate(String purchaseDate) {
        this.purchaseDate = purchaseDate;
    }
}

DAOの作成

今回追加したメソッドは、下記の通りになります。

findById idから家電データを検索します。 編集するデータを特定するために使っています。

update 家電データを更新します。

package com.pom2019.Struts2Web.entities.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.pom2019.Struts2Web.entities.HouseholdAppliances;

public class HouseholdAppliancesDao {

    private SessionFactory sf;

    public HouseholdAppliancesDao() {
        super();
    }

    public HouseholdAppliancesDao(SessionFactory sf) {
        super();
        this.sf = sf;
    }

    @SuppressWarnings("unchecked")
    public List<HouseholdAppliances> findAll() {
        Session ss = sf.openSession();
        return ss.createQuery("from HouseholdAppliances").list();
    }

    @SuppressWarnings("unchecked")
    public List<HouseholdAppliances> findById(String id) {
        Session ss = sf.openSession();
        return ss.createQuery("from HouseholdAppliances "
                + "where id = " + id).list();
    }

    public boolean save(HouseholdAppliances h) {
        Session ss = sf.openSession();
        Transaction trans = null;
        try {
            trans = ss.beginTransaction();
            ss.save(h);
            trans.commit();
        } catch (Exception e) {
            trans.rollback();
            return false;
        } finally {
            ss.close();
        }
        return true;
    }

    public boolean update(HouseholdAppliances h) {
        Session ss = sf.openSession();
        Transaction trans = null;
        try {
            trans = ss.beginTransaction();
            ss.update(h);
            trans.commit();
        } catch (Exception e) {
            trans.rollback();
            return false;
        } finally {
            ss.close();
        }
        return true;
    }
}

コントローラの作成

今回編集もしくは追加したアクションは、下記の通りになります。

dispModify idから家電データを検索し、検索されたデータをモデルにセットしています。

update モデルから家電データを取得し、テーブルを更新しています。

   
    @Action(value = "dispModify", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayModify.jsp")
    })
    public String dispModify() {
        String id = indexModel.getId();
        
        //idがパラメータとして存在した場合(編集の場合)
        if (id != null && !"".equals(id)) {
            SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
            
            HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
            List<HouseholdAppliances> hList = hDao.findById(id);

            if (hList.size() > 0) {
                //編集する家電情報を取得する
                HouseholdAppliances h = hList.get(0);
                indexModel.setHouseholdAppliancesName(h.getHouseholdAppliancesName());
                indexModel.setPurchaseDate(new SimpleDateFormat("yyyy/MM/dd").format(h.getPurchaseDate()));
            }
        }
        
        return ActionSupport.SUCCESS;
    }
    
    @Action(value = "update", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayModify.jsp")
    })
    public String update() {
        //パラメータの取得
        String id = indexModel.getId();
        String householdAppliancesName = indexModel.getHouseholdAppliancesName();
        String purchaseDate = indexModel.getPurchaseDate();
        
        //編集用インスタンスの取得
        SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
        HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
        HouseholdAppliances h = hDao.findById(id).get(0);
        
        //家電名の設定
        h.setHouseholdAppliancesName(householdAppliancesName);
        //購入日時の設定
        Date d = new Date();
        try {
            d = new SimpleDateFormat("yyyy/MM/dd").parse(purchaseDate);
        } catch(ParseException e) {}
        h.setPurchaseDate(d);
        
        //更新処理
        hDao.update(h);
        
        return ActionSupport.SUCCESS;
    }

実行結果

idが6のデータを編集します。 f:id:pom2019:20190928160147p:plain

編集画面に遷移しました。 f:id:pom2019:20190928160159p:plain

データを編集後、保存ボタンをクリックします。 f:id:pom2019:20190928160209p:plain

データが編集されました。 f:id:pom2019:20190928160220p:plain

おわりに

新規保存の際と変わったことは、DAOで「ss.save(h);」を呼ぶのではなく、「ss.update(h);」を呼んでいる点です。

「ss.update(h);」にセットしているエンティティhは、もちろん存在するエンティティを指定しないとエラーとなってしまいます。

存在するエンティティを取得するために、findByIdメソッドを使っていたのです。

逆に「ss.save(h);」にセットしているエンティティhは、家電情報テーブルに存在しない新規インスタンスをセットしなければエラーとなってしまいます。

最後までお読み頂きありがとうございました。