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

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

新しいブログを作成しました!

はてなブログでグーグルアドセンスに挑戦していたのですが、どうしても「サイトの停止または利用不可」を解決できず、断念。。

結局WordPressでブログを立ち上げてなんとか合格することができました。

これからは主にWordPressでブログ作成を進めていきたいと思っています。

もしご興味のある方がおられましたら、下記サイトにアクセスください。

iteng-pom.com

いつもはてなスターはてなブックマークを頂いている方、本当にありがとうございます。

これからもゆるい感じでブログ運営を進めていきたいと思っておりますので、よろしくお願いします。

Ubuntuのローカル環境でGitサーバーを構築してみよう!

こんにちは、ぽむです。

今回は、Ubuntuのローカル環境でGitサーバーを構築する手順をご紹介したいと思います。

はじめに

Ubuntuのローカル環境でGitサーバーを構築する利点を上げるとすると主に下記3点が思い浮かびます。

  • ローカル環境でGitを管理するためカスタマイズし易い。

  • 複数人でGitを共有する場合でも人数制限がない。

  • Gitサーバーを構築することでサーバー構築の勉強になる。

Gitは代表的なバージョン管理ツールです。バージョン管理ツールとはソースの変更履歴を管理するためのツールのことです。

バージョン管理ツールは、SVNやGitなどが有名です。

本ページ引っ越しのご案内

本ページは引っ越しました。

お手数ですが、続きは下記URLまでアクセスください。

iteng-pom.com

Spring5とHibernate5.2を使ってテーブルデータを一覧表示してみよう!

こんにちは、ぽむです。

今回は、Spring5とHibernate5.2を使ってMySQL内のテーブルデータを一覧表示させるプログラムをご紹介したいと思います。

開発環境

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

Spring5.2.1.RELEASE
Hibernate5.2.10.Final
MySQL8.0.16

はじめに

前回ご紹介させていただいたブログでSessionFactoryをBeanとして登録する方法を書かせていただいたのですが、今回はこのSessionFactoryを使って、MySQL内のテーブルからデータを取ってきてそのデータを画面上に表示させるプログラムをご紹介したいと思います。

前回ご紹介させていただいたブログについては下記リンクをご参照下さい。

今回のポイントは、MySQL内のテーブルからデータを取ってくる処理をサービスとしてまとめることです。このサービスをアクションメソッドから呼び出せばアクションメソッドをきれいに書くことができます。

Springフレームワークには、DIコンテナに登録するBeanとして、「@Component、@Controller、@Service、@Repository」などがありますが、DAOといったデータ操作に関するBeanはサービスとして登録する決まりがあります。

それぞれの違いは下記URLに詳しく載っているので、よかったら参考にして下さい。KevinFQさんありがとうございます。

サービスクラスの作成

  • サービスクラスに@Serviceアノテーションを付けます。
  • SessionFactoryを取得できるBeanまでのパッケージを@ComponentScanします。
  • @Autowiredアノテーションを使ってSessionFactoryを注入します。
  • findAllメソッド内でテーブルデータを全検索して結果を返します。
package com.pom2019.service;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import com.pom2019.entity.HouseholdAppliances;

@Service
@ComponentScan("com.pom2019.config")
public class HouseholdAppliancesDao {

    @Autowired
    private SessionFactory sf;

    public HouseholdAppliancesDao() {
        super();
    }

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

コントローラクラスの作成

  • @Controllerを付与して本クラスがコントローラクラスであることを宣言します。
  • サービスBeanのあるクラスまでのパッケージをコンポネートスキャンします。
  • @Autowiredアノテーションを使ってサービスBeanを注入します。
  • @RequestMappingアノテーションを使ってアクションパスを宣言します。
  • 注入したservice変数を使ってテーブルデータを取得し、モデルにセットします。
  • 最後にview名を返します。
package com.pom2019.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.pom2019.entity.HouseholdAppliances;
import com.pom2019.service.HouseholdAppliancesDao;

@Controller
@ComponentScan("com.pom2019.service")
public class IndexController {
    @Autowired
    private HouseholdAppliancesDao service;
    
    @RequestMapping(value="/getList", method = RequestMethod.GET)
    public String execute(Model model) {
        List<HouseholdAppliances> list = service.findAll();
        model.addAttribute("list", list);
        
        return "displayList";
    }
    
}

Viewの作成

  • ページディレクティブでコンテントタイプと文字コードを指定します。(1行目)
  • taglibディレクティブでJSTLタグライブラリを使うことを宣言します。(2,3行目)
  • c:forEachタグを使ってモデルにセットされたlistデータを取得しています。(1行分が変数dataに取得されます)
  • c:outタグを使ってデータを出力しています。
  • fmt:formatDateタグを使って日付データを出力しています。
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>家電リスト</title>
        <style>
    table {
        border-collapse: collapse;
    }
    td {
        border: 1px solid gray;
        padding: 3px 8px;
    }
    </style>
</head>
<body>
<h2>家電リスト</h2>

<p>
    <button id="btnNew">新規</button>
</p>

<table>
    <tr>
        <td>id</td>
        <td>家電名</td>
        <td>購入日時</td>
        <td colspan="2">アクション</td>
    </tr>
    <c:forEach var="data" items="${list}">
        <tr>
            <td class="id"><c:out value="${data.id}"/></td>
            <td><c:out value="${data.householdAppliancesName}"/></td>
            <td><fmt:formatDate value="${data.purchaseDate}" type="DATE" pattern="yyyy/MM/dd"/></td>
            <td><button class="btnEdit">編集</button></td>
            <td><button class="btnDelete">削除</button></td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

実行結果

mvc-config.xml内でコントローラクラスをコンポネートスキャンするように設定後、実行します。

f:id:pom2019:20200113145605p:plain

(注意)新規/編集/削除ボタンは今回使用しておりません。

おわりに

MySQL内のテーブルデータを無事表示することができました。

Springフレームワークを使ってそれぞれのクラスをBeanとして部品化すれば、ベタ書きのJavaで書いていたような(フレームワークを使わないJDBCを使ったJavaのような)長い処理は書かなくていいし、全体の見通しも良くなると思います。

今回のプログラムが参考になりましたら、皆様もぜひ活用して下さいね!

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

Spring5とHibernate5.2を使ってSessionFactoryをBeanとして取得してみよう!

こんにちは、ぽむです。

年末年始は時間の空いてるときに、過去のブログを更新していました。誤字脱字、言葉の表現がおかしいところなどをまとめて修正しました。日本語ってホント難しいです。。

令和2年ものろのろしたペースでブログを更新していきたいと思っています。本年もよろしくお願い申し上げます。

今回は、Spring5フレームワークとO/RマッパであるHibernate5.2を使ってSessionFactoryをBeanとして取得する方法をご紹介したいと思います。

はじめに

SessionFactoryは、データベースのデータを操作する際にWebアプリケーションとデータベースの橋渡し役として必要になります。

SessionFactory is an interface. SessionFactory can be created by providing Configuration object, which will contain all DB related property details pulled from either hibernate.cfg.xml file or hibernate.properties file. SessionFactory is a factory for Session objects.

We can create one SessionFactory implementation per database in any application. If your application is referring to multiple databases, then you need to create one SessionFactory per database.

※下記リンクを引用させて頂きました。ありがとうございます。

What is SessionFactory in Hibernate? - Hibernate Tutorials

データの操作とは、主にデータベースのデータを取得・保存・更新・削除することです。データを操作するプログラムを集めたものをDAO(Data Access Objectsの略)といいます。

引用元にある通り(英語の引用元でごめんなさい。。僕は簡単な英語、見たことのある専門用語なら分かります!)、SessionFactoryを取得するにはhibernate.cfg.xmlファイルもしくはhibernate.propertiesファイルに関連付けられたデータベースから取得できます。

今回は、hibernate.cfg.xmlファイルからSessionFactoryを取得する方法をご紹介したいと思います。

開発環境

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

Spring5.2.1.RELEASE
Hibernate5.2.10.Final
MySQL8.0.16

hibernate.cfg.xmlファイル

hibernate.cfg.xmlファイル内で下記の設定を行っています。

  • データベースのドライバ
  • データベースへの接続文字列
  • O/Rマッパの設定
  • エンティティの宣言

リソースフォルダに配置すれば、自動的に認識してくれます。

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://127.0.0.1:3306/TESTDB?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <property name="connection.username">test</property>
        <property name="connection.password">****</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        
        <!-- Mapping file inclusion -->
        <mapping class="com.pom2019.entity.HouseholdAppliances"/>

    </session-factory>
</hibernate-configuration>

※パスワードはマスキングしています。

Configファイル

詳細は下記の通りとなっています。

  • Configurationアノテーション→設定ファイルとしてSpringが認識してくれます。ここでは絶対パスとなっていますが、これはHibernateのConfigurationクラスとクラス名が被っているからです。

  • Beanアノテーション→BeanクラスとしてSpringが認識してくれます。

  • SessionFactoryの取得hibernate.cfg.xmlファイルから設定を読み込みSessionFactoryを取得しています。SessionFactoryが取得できたら、取得できたことをコンソールに出力しています。

package com.pom2019.config;

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class HibernateConfig {

    @Bean
    public SessionFactory sessionFactory() {
        SessionFactory sessionFactory = null;
        
        try {
            //registryの作成
            StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();

            //MetadataSourcesの作成
            MetadataSources sources = new MetadataSources(registry);

            //Metadataの作成
            Metadata metadata = sources.getMetadataBuilder().build();

            //SessionFactoryの作成
            sessionFactory = metadata.getSessionFactoryBuilder().build();
            
            //ログの出力
            if (sessionFactory != null) {
                System.out.println("セッションファクトリーを取得できました!");
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        
        return sessionFactory;
    }
}

サーバーの起動

HibernateConfigファイルをComponentScanの対象にして、サーバーを起動します。

1 04, 2020 2:49:53 午後 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 2646 ms
INFO  ContextLoader - Root WebApplicationContext: initialization started
INFO  ContextLoader - Root WebApplicationContext initialized in 419 ms
INFO  DispatcherServlet - Initializing Servlet 'dispatcherServlet'
INFO  Version - HHH000412: Hibernate Core {5.2.10.Final}
INFO  Environment - HHH000206: hibernate.properties not found
INFO  Version - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
WARN  pooling - HHH10001002: Using Hibernate built-in connection pool (not for production use!)
INFO  pooling - HHH10001005: using driver [com.mysql.cj.jdbc.Driver] at URL [jdbc:mysql://127.0.0.1:3306/TESTDB?useUnicode=true&characterEncoding=UTF-8]
INFO  pooling - HHH10001001: Connection properties: {user=test, password=****}
INFO  pooling - HHH10001003: Autocommit mode: false
INFO  DriverManagerConnectionProviderImpl - HHH000115: Hibernate connection pool size: 1 (min=1)
INFO  Dialect - HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
セッションファクトリーを取得できました!
INFO  DispatcherServlet - Completed initialization in 4332 ms
1 04, 2020 2:50:01 午後 org.apache.catalina.startup.Catalina start
情報: Server startup in 7681 ms

おわりに

SessionFactoryが無事取得できました。

SessionFactoryがBeanとして取得できたので、SessionFactoryを使いたいときにこのBeanを注入(Autowired)してあげれば、いつでもSessionFactoryを使うことができます。

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

Struts2の実装例まとめ!(Webアプリを作ってみよう)

こんにちは、ぽむです。

今回はこれまでご紹介したデータベースのインストールからStruts2での簡単なWebアプリケーション作成までを、一覧できるようにまとめてご紹介したいと思います。

はじめに

Struts2は、「アパッチストラッツプロジェクトがオープンソースとして開発したJavaのWebアプリケーションフレームワーク」です。

以前に一世を風靡したStrutsは、同じプロジェクトが開発したフレームワークですが、Struts2とは構造が全く別物のようです。 現在はStrutsの更新(セキュリティパッチ)は行われておらず、WebサイトでStrutsをダウンロードすることができますが、今も更新が行われているStrus2をダウンロードするように推奨されています。

Struts2は、アノテーションによる設定ファイルの削減、POJOによるアクションファイルの作成、OGNL (Object-Graph Navigation Language) と呼ばれる式言語による動的パラメータの作成などができるようになっています。

詳しくは下記サイトをご参照下さい。

struts.apache.org

プロジェクト作成に関する内容

統合開発環境のインストールと日本語化、ブランクプロジェクトの作成については、下記リンクを参考にして下さい。

データベースに関する内容

MySQLのインストール、MySQLワークベンチのインストール、テーブルの作成などデータベースに関する内容については、下記リンクを参考にして下さい。

O/Rマッパに関する内容

O/Rマッパの使用方法、Entityの自動生成、自動生成したEntityの表示方法などO/Rマッパに関する内容については、下記リンクを参考にして下さい。

セッションファクトリーに関する内容

DBとWebアプリケーションを紐付けるセッションファクトリーに関する内容については、下記リンクを参考にして下さい。

簡単なWebアプリケーションを作ってみよう

CRUD操作を行う簡単なWebアプリケーションについては、下記リンクを参考にして下さい。 CRUD操作とは、データベースの基本操作であるCreate(新規に作成する)、Read(データを選択する)、Update(更新する)、Delete(削除する)を行う処理のことを言います。

おわりに

データベースのインストールから簡単なWebアプリケーションの作成までをご紹介してきましたが、いかがでしたでしょうか?

Struts2フレームワークを使えば、フレームワークを使わないサーブレットでWeb.xmlにすべて設定内容を書いていたのようなめんどくさいことはしなくていいし、アクションファイルもPOJOで書けるのでソース管理もし易いし、開発者にとって優しい感じがします。

皆様にもぜひStruts2の便利さ、使い易さを体感して頂きたいです。

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

デュアルブートのUbuntuが起動しなくなった!【解決済】

こんにちは、ぽむです。

デュアルブートUbuntuがある日突然起動しなくなりました。

簡単な設定変更で問題解決することができたので、今回はその解決方法をお伝えしようと思います。

 

その時はある日突然起こりました。。

いつものようにパソコンを立ち上げるとパソコンが起動しない。。

何度かパソコンを立ち上げてみるもブラックスクリーンのままです。。

BIOSさえ立ち上がらないので泣きそうになりましたね。。

電源長押しで再度立ち上げてを繰り返すこと数回、やっとWindowsが立ち上がりました。

(立ち上がった原因は不明。。)

本ページ引っ越しのご案内

本ページは引っ越しました。

お手数ですが、続きは下記URLまでアクセスください。

iteng-pom.com

 

 

Springでjsonを取得するREST APIを作成しよう!

前回まで取り上げていたStruts2でも同じことができるのですが、今回は今一番ホットなSpringで、jsonを返すREST APIを作成したいと思います。

また、REST APIには、jsonを返すパターンとxmlを返すパターンがあるのですが、それぞれ得意不得意な表現があり、どちらを使えばいいか一概に言えませんが、今回はjsonを返すプログラムで作成していきます。

jsonは、「JavaScript Object Notaion」の略でどのようなデータを持つかを示すデータ定義言語です。

本ページ引っ越しのご案内

本ページは引っ越しました。

お手数ですが、続きは下記URLまでアクセスください。

iteng-pom.com

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

こんにちは、ぽむです。

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

はじめに

前回までで、O/Rマッパを使った新規保存と編集を見てきました。

pom2019.hatenablog.com

pom2019.hatenablog.com

今回は、O/Rマッパを使った削除をお伝えしたいと思います。

前回までの表示(SELECT文)と新規保存(INSERT文)と編集(UPDATE文)、今回お伝えする削除(DELETE文)を合わせると、テーブルの4つの基本操作をO/Rマッパですべてご紹介できたことになります。

開発環境

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

Struts22.5.14.1
Hibernate4.3.0.Final
MySQL8.0.16

ビューの作成

javascript 削除ボタンをクリックした場合の処理を追加しました。

<%@ 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;
    }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<h2>家電リスト</h2>

<p>
    <button id="btnNew">新規</button>
</p>

<table>
    <tr>
        <td>id</td>
        <td>家電名</td>
        <td>購入日時</td>
        <td colspan="2">アクション</td>
    </tr>
    <s:iterator value="list">
        <tr>
            <td class="id"><s:property value="id"/></td>
            <td><s:property value="householdAppliancesName"/></td>
            <td><s:date name="purchaseDate" format="yyyy/MM/dd"/></td>
            <td><button class="btnEdit">編集</button></td>
            <td><button class="btnDelete">削除</button></td>
        </tr>
    </s:iterator> 
</table>

<script>
   $(function() {
       //新規ボタン
       $('#btnNew').on('click', function() {
           //クエリ文字列で新規登録フラグを立てます
           location.href = "${pageContext.request.contextPath}/dispModify?isNew=true";
       });

       //編集ボタン
       $('.btnEdit').on('click', function() {
           var id = $(this).parents("tr").find(".id").html();
           
           //クエリ文字列でidを渡します
           location.href = "${pageContext.request.contextPath}/dispModify?id=" + id;
       });

       //削除ボタン
       $('.btnDelete').on('click', function() {
           //削除する行のidを取得
           var id = $(this).parents("tr").find(".id").html();

           //フォームデータの取得
           var fd = new FormData();
           
           //フォームデータの追加
           fd.append("id", id);
           
           //urlの設定
           var url = "${pageContext.request.contextPath}/delete";
           
           //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を追加していたため、今回は変更していません。

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から検索して削除する家電データ(オブジェクト)を取得します。

delete 引数に与えられた家電データ(オブジェクト)を実際に削除します。

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;
    }

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

コントローラの作成

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

delete idから家電データ(オブジェクト)を取得して、削除処理を実行しています。

package com.pom2019.Struts2Web.actions;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.pom2019.Struts2Web.entities.HouseholdAppliances;
import com.pom2019.Struts2Web.entities.dao.HouseholdAppliancesDao;
import com.pom2019.Struts2Web.model.IndexModel;
import com.pom2019.listener.HibernateListener;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletContext;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.util.ServletContextAware;
import org.hibernate.SessionFactory;

@Namespace("/")
@ParentPackage("struts-default") @Action(value = "delete", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayList.jsp")
    })
    public String delete() {
        //パラメータの取得
        String id = indexModel.getId();
        
        //削除用インスタンスの取得
        SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
        HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
        HouseholdAppliances h = hDao.findById(id).get(0);
        
        //削除処理
        hDao.delete(h);
        
        //エラー回避用に空変数をセット
        indexModel.setList(new ArrayList<HouseholdAppliances>());

        return ActionSupport.SUCCESS;
    }

public class Index extends ActionSupport implements ServletContextAware, ModelDriven<IndexModel> {
    private static final long serialVersionUID = -1884587001523422505L;
    ServletContext context;
    private IndexModel indexModel = new IndexModel();
    
    @Action(value = "display", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayList.jsp")
    })
    public String execute() {
        SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
        
        HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
        List<HouseholdAppliances> hList = hDao.findAll();
        indexModel.setList(hList);
        
        return ActionSupport.SUCCESS;
    }
    
    @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 = "save", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayModify.jsp")
    })
    public String save() {
        //パラメータの取得
        String householdAppliancesName = indexModel.getHouseholdAppliancesName();
        String purchaseDate = indexModel.getPurchaseDate();
        
        //保存用インスタンスの生成
        HouseholdAppliances h = new HouseholdAppliances();
        
        //家電名の設定
        h.setHouseholdAppliancesName(householdAppliancesName);
        //購入日時の設定
        Date d = new Date();
        try {
            d = new SimpleDateFormat("yyyy/MM/dd").parse(purchaseDate);
        } catch(ParseException e) {}
        h.setPurchaseDate(d);
        
        //保存処理
        SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
        HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
        hDao.save(h);
        
        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;
    }
    
    @Action(value = "delete", results = {
            @Result(name = "success", location = "/WEB-INF/content/displayList.jsp")
    })
    public String delete() {
        //パラメータの取得
        String id = indexModel.getId();
        
        //削除用インスタンスの取得
        SessionFactory sf = (SessionFactory) context.getAttribute(HibernateListener.KEY_NAME);
        HouseholdAppliancesDao hDao = new HouseholdAppliancesDao(sf);
        HouseholdAppliances h = hDao.findById(id).get(0);
        
        //削除処理
        hDao.delete(h);
        
        //エラー回避用に空変数をセット
        indexModel.setList(new ArrayList<HouseholdAppliances>());

        return ActionSupport.SUCCESS;
    }

    public void setServletContext(ServletContext context) {
        this.context = context;
    }

    @Override
    public IndexModel getModel() {
        return indexModel;
    }
}

実行結果

idが6のデータを削除します。 f:id:pom2019:20191019194751p:plain

idが6のデータが削除されました。 f:id:pom2019:20191019194812p:plain

おわりに

4つの基本操作を知っていれば、ちょっとしたシステムを構築できるようになります。

ここをスタート地点として、複数プライマリキーのテーブルを扱ったり、テーブル数を増やしていけば、扱える処理も増えていくことになります。

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

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は、家電情報テーブルに存在しない新規インスタンスをセットしなければエラーとなってしまいます。

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