Beginner's Hack

復習用。誰かのためになれば...

Java - 配列のコピーと比較

Java Silver試験対策

前提

配列をclone()メソッドで複製すると、新しいインスタンスが生成される。

String[] origin = new String[] {"1", "2"};
String[] reprica = origin.clone();

System.out.println("origin == reprica: " + (origin == reprica));

// 出力結果
// origin == reprica: false

参照型(Object)の場合は注意が必要

複製した配列が異なるインスタンスであることは上記で説明した通り。

ただ、その配列に含まれているオブジェクトは同一である。

String[] origin = new String[] {"1", "2"};
String[] reprica = origin.clone();

System.out.println("origin[0] == reprica[0]: " + (origin[0] == reprica[0]));

// 出力結果
// origin[0] == reprica[0]: true

ここで、配列の要素がStringと違い、変更可能なオブジェクトであった場合を考える。

String[][] origin = new String[][] {{"1", "2"}, {"3", "4"}};
String[][] reprica = origin.clone();

System.out.println("origin[0] == reprica[0]: " + (origin[0] == reprica[0]));

reprica[0][0] = "10";

System.out.println("reprica[0][0]: " + reprica[0][0]);
System.out.println("origin[0][0]: " + origin[0][0]);

// 出力結果
// origin[0] == reprica[0]: true
// reprica[0][0]: 10
// origin[0][0]: 10

このように、複製した配列内の配列は同一オブジェクトの為、repricaの配列を操作するとoriginに影響するので注意が必要である。

java 配列の宣言とか初期化とか

java silver 試験対策の整理

宣言

型か変数名のいずれかに[]をつけることで配列を表すことができる。

多次元配列の場合は次元の数だけ[]を増やせばいい。

また次元数は型と変数名の合計であり、arr5は二次元配列になるので要注意。

// 一次元配列
int[] arr1;
int arr2[];

// 二次元配列
int[][] arr3;
int arr4[][];
int[] arr5[];

サイズの指定

配列を宣言しただけでは要素数が指定されておらず、値を代入することができない。

newを使用して要素数を指定することで、値を代入することが可能になる。

// 一次元配列
int[] arr;
arr = new int[2];
arr[0] = 5;

// 二次元配列
int[][] arr2;
arr2 = new int[2][3];
arr2[0][0] = 10;

POINT: 二次元配列のサイズ指定時は、二次元目の[3][]として指定しないことも可能。

宣言と同時に初期化を行う

宣言と同時に初期化を行う方法には以下の3通りがある。

// 上記で説明した2つを同時に行うパターン
int[] arr1 = new int[2];

// 無名配列を代入するパターン
int[] arr2 = new int[] {1, 2};

// 初期化子を使用するパターン
int[] arr3 = {1, 2{};

POINT: 無名配列では[]内にサイズは指定しない。

POINT: 無名配列の[]の数は次元数と対応させる。ex) int[][] arr = new int[][] {{1, 2}, {3, 4}};

POINT: 初期化子は宣言時にのみ使用可能。代入などでは使用できない。

javanal#3 - DBコンテナの作成(postgreSQL)

概要

dockerでDBコンテナを起動して、コマンドラインから接続してみる。

手順

docker-compose.ymlの編集

  db:
    image: postgres
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      PGDATA: /data/postgres
    volumes:
       - postgres:/data/postgres
    ports:
      - "5432:5432"
    restart: unless-stopped

# docker領域内にpostgresという名前のボリュームを確保
# dbコンテナを削除してもデータが消えない
volumes:
    postgres:

DBコンテナ起動確認

コンテナの起動。docker-compose.ymlが置いてあるディレクトリで次のコマンドを実行する。

$ docker compose up -d

次のコマンドで、dbコンテナに移動する

docker exec -it xxx bash

xxxはコンテナ名。 psコマンドで確認することができる。

docker ps

DB接続確認

dbコンテナにアクセスできれば次のコマンドでdbに接続する

$ psql -d [DB名] -U [user名]

dbにアクセスできれば、docker上で問題なくdbコンテナが起動していることがわかる。

javanal#2 - webコントローラの作成

javanal#1 - javaでtwitter風webアプリを作る(環境構築) - Beginner's Hack

概要

依存関係に追加したSpring Webの機能を使用して、"http://localhost:8080/home"にアクセスするとHello Worldが表示されるようにする。

手順

コントローラの作成

// spring bootにコントローラであると認識させる
@Controller
// リクエストURLが"/xxx"であればこのコントローラ内のメソッドにルーティングされる
@RequestMapping("/")
public class HomeController {

  // リクエストURLが"/home"かつ、リクエストタイプが"GET"であればこのメソッドが実行される
  @GetMapping("home")
  public String home() {

    // 表示するhtml名を表す
    // この場合templatesフォルダ内のhome.htmlを表示する
    return "home";
  }
}

ビューの作成

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Javanal</title>
    </head>
    <body>
        <p>Hello World</p>
    </body>
</html>

動作確認

/homeにアクセスするとHello Worldが表示される

javanal#1 - javaでtwitter風webアプリを作る(環境構築)

背景

spring securityやORMなど、業務で使用するライブラリ、フレームワークの練習台としてtwitter風のwebアプリを作ってみようと思いました。

java + journalでjavanalなんて名前をつけて、ゆっくりやっていきます。

とりあえず今日は環境構築をやっていきます。

環境構築

ホストPCに色々インストールするのは嫌だったので、Dockerコンテナ上で開発をしていきます。

Docker + VS Code Remote-Container
docker image: openjdk:17.0.2-jdk-slim-bullseye

java: 17.0.2
フレームワーク: spring boot 2.7.3

プロジェクト作成

Spring Initializrを使用してspring bootプロジェクトを作成します。

画面右上の「ADD DEPENDENCIES...」ボタンから好きな依存関係を追加できます。

とりあえずURLにアクセスして画面を表示させたかっただけなので、lombokとwebを追加しました。

設定ができたら画面中央下部の「GENERATE」でプロジェクトをダウンロードします。

Spring Initializr - javanal

プロジェクトのzipファイルがダウンロードが完了すれば、任意のフォルダに解凍します。

今後は、この解凍したプロジェクトを含むディレクトリをルートディレクトリとして進めていきます。

Docker環境構築

作成したプロジェクトの実行環境を構築していきます。

ルートディレクトリ直下にdockerフォルダを作成し、その配下に下記のようにフォルダとファイルを作成します。

.
├── README.md
├── docker
│   ├── app
│   │   └── Dockerfile
│   └── docker-compose.yml
└── javanal

docker-compose.yml

services:
  app:
    build:
      context: ..
      dockerfile: ./docker/app/Dockerfile
    # tty: true、もしくはフォアグラウンドで実行しているプロセスがあればコンテナが停止しない
    tty: true
    # source(ホストマシン)のディレクトリをtarget(コンテナ)にマウントする
    volumes:
      - type: bind
        source: ../javanal
        target: /app
    ports:
      - target: 8080
        published: ${WEB_PORT:-8080}
        protocol: tcp
        mode: host
    #コンテナ内のワーキングディレクトリ
    working_dir: /app

Dockerfile

FROM openjdk:17.0.2-jdk-slim-bullseye

Docker動作確認

上記の手順でdocker-compose.ymlとDockerfileを作成した後、ymlファイルが存在するディレクトリで下記コマンドを実行します。

$ docker compose up -d

以下のようなメッセージが出れば成功です。

[+] Running 1/1
 ⠿ Container docker_app_1  Started                                                                                                                               3.7s

VS Code Remote-Containerの環境設定

javaの開発は、上記コンテナ内のソースコードを編集・デバッグしながら開発を行なっていきますが、Dockerコンテナを起動しただけでは、コンテナ内のソースコードを編集することができません。

そこで、VS Code拡張機能であるRemote-Containerを使用することによって、VSCode上でコンテナ内のソースコードを編集できるようにします。

拡張機能のインストール

VSCodeの画面でcmd + shift + xのショートカットを押して、拡張機能ページを表示させます。 検索エリアに「remote」と入力すると、下記のRemote Developmentがヒットするのでインストールします。

Remote-Containerインストール

devcontainer.jsonの作成

下記のように.decontainerフォルダ, devcontainer.jsonを作成します。

├── .devcontainer
│   └── devcontainer.json
├── README.md
├── docker
│   ├── app
│   │   └── Dockerfile
│   └── docker-compose.yml
└── javanal

devcontainer.json

{
  // 任意の名前
  "name": "remote-java",
  // DockerComposeFileを指定
  "dockerComposeFile": "../docker/docker-compose.yml",
  // DockerComposeFileにあるservice名を指定
  "service": "app",
  // コンテナに入ったときの作業ディレクトリ
  "workspaceFolder": "/app",
  "settings": {
      // bashでターミナルを起動
      "terminal.integrated.defaultProfile.linux": "bash"
  },
  // コンテナ内で使いたい拡張機能
  "extensions": [
    // Java関連の拡張機能パック
    "vscjava.vscode-java-pack",
    // Spring Boot関連の拡張機能パック
    "pivotal.vscode-boot-dev-pack",
    "gabrielbb.vscode-lombok"
  ]
}

Remote - Container動作確認

ルートディレクトリでcmd + shift + P を押してコマンドパレットを開く。

「Remote-Containers: Reopen in Container」と入力し、実行する。

画面左下の表示が次の通りになれば起動完了。

Remote-Container起動中

Remote-Container起動完了

これで環境構築は終了

MavenプロジェクトでMybatis generatorを使用する

手順

DBにテーブルを作成

  • DBにアクセス
  • CEATE TABLE
  • 今回はDockerコンテナを使用するため、下記の手順で行なった。

DockerのDBコンテナに入ってクエリを実行する - Beginner's Hack

Mybatis generatorの導入

  • pom.xmlにpluginを追加。
   <project ...>
     ...
     <build>
       ...
       <plugins>
        ...
        <plugin>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-maven-plugin</artifactId>
          <version>1.4.1</version>
        </plugin>

        <!-- DBにアクセスするためのドライバ -->
        <!-- pom.xmlに記述しない場合は後述のgeneratorConfig.xmlに記載する -->
        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
           </dependency>
         </dependencies>
        ...
      </plugins>
      ...
    </build>
    ...
  </project>

generatorConfig.xmlの作成

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration >
  <!-- pom.xmlにドライバーの依存関係を追加しているため、classPathEntryの記述は不要 -->
  <!-- <classPathEntry location="C:\Program Files\MySQL\Connector.J 5.1\mysql-connector-java-5.1.33-bin.jar"/> -->
  <context id="context1" targetRuntime="MyBatis3Simple">
    <!-- コメント生成の抑制 -->
    <commentGenerator>
        <property name="suppressAllComments" value="true" />
    </commentGenerator>

    <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
      connectionURL="jdbc:mysql://mysql/sample_schema"
      userId="dev_usr"
      password="dev_usr_pass">
    </jdbcConnection>

    <javaModelGenerator targetPackage="com.example.demo.MBGEntity" targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
      <property name="trimStrings" value="true" />
    </javaModelGenerator>

    <sqlMapGenerator targetPackage="com.example.demo.MBGSql"  targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>

    <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.demo.MBGMapper"  targetProject="src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>

    <table schema="sample_schema" tableName="account">
    </table>
  </context>
</generatorConfiguration>

Mybatis generatorの実行

DockerのDBコンテナに入ってクエリを実行する

手順

コンテナ起動

docker-compose.ymlが配置してあるディレクトリにて

$ docker compose up -d

DBに接続

MySQLの場合

$ mysql -u root -p 
Enter password: <-コンソールには表示されないがパスワードを入力してEnter

データベース(スキーマ)作成

mysql> CREATE DATABASE [DB名];

テーブル作成

mysql> CREATE TABLE sample_mybatis.account(
    -> account_id int PRIMARY KEY AUTO_INCREMENT
    -> ,name varchar(30)
    -> );

テーブル確認

mysql> DESC sample_mybatis.account;