JavaにおけるDB操作（その１）


NonJava開発者が諸事情でHibernate利用しなければならない状況になったので基本部分を含めメモ。

## パターン？

JavaでDBを操作するパターンはいくつか。まあ、他の言語とパターン的には変わらない。

* JDBCでまんま接続
* DAO/DTOパターン？
* Hibernate（O/Rマッパ利用）

>Hibernateは長いので[別記事](https://qiita.com/zaburo/private/28c4af4233e4a4f46391)にしました。

## 環境

Javaの開発環境はもっさりしているので好きじゃない。いつもどおりvscodeで。

* macOS利用
* 開発環境はvscode(java extension入り）とコマンドライン

>MacでのJava環境作りは[こちら](https://qiita.com/zaburo/items/cd4923e52ffbf70658ab)を。

## DBの準備

私はMacでMAMPのMySQLを利用していますが、何でもOK。

```bash
create database testdb;
use testdb;

create database users(
	id int primary key auto_increment,
	name varchar(32),
	age int
);

insert into users(name,age) values('hoge',11);
insert into users(name,age) values('foo',22);
```

>初期ではid,passwordはroot, rootですね。


## 雛形生成

mavenを利用します。mavenとはなんぞという人はこちら（私もそのレベル）。

```bash
mvn archetype:generate \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=RELEASE \
-DinteractiveMode=false \
-DgroupId=com.hoge \
-DartifactId=jdbc-db-test
```

### pom.xmlの編集（抜粋）

pom.xmlのdependenciesに以下を追加。

```xml:pom.xml

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.23</version>
    </dependency>
    
```

>最新バージョンは[ここ](https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.23)で確認。


## JDBC まんま

### 実装

```java
package com.hoge;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class App {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "root");
            stmt = conn.prepareStatement("select * from users where name like ?"); // '%?%'はエラーとなる
            stmt.setString(1, "%" + "hoge" + "%");
            rs = stmt.executeQuery();

            while (rs.next()) {
                String id = rs.getString("id");
                String name = rs.getString("name");
                String age = rs.getString("age");

                System.out.println(id + " " + name + " " + age);
            }

        } catch (SQLException e) {
            System.out.println("データベースエラー");
        } finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                System.out.println("error");
            }
        }
    }
}
```

### 実行

vscodeのjava extensionの実行を利用しているが、下記ので実行可能。

```bash
mvn -q compile exec:java -Dexec.mainClass=com.hoge.App
```

こんな感じででるはず。

```bash
1 hoge 11
```

## DAO/DTOパターン

Javaのコード見てるとよくDAOとか出てくるので軽くおさらい。

### ファイル構造

最終的に下記のようになります。実行ファイルはApp.javaのまま。

![スクリーンショット 2021-03-18 11.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/36458639-e1e7-ad91-0249-6bbea0b46594.png "スクリーンショット 2021-03-18 11.22.10.png")


### DTO（Data Transfer Object）

まあ、Transferというよりモデル。

```java:User.java
package com.hoge;

public class User {
    private int id;
    private String name;
    private int age;

    public User(int id,String name,int age){
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
```

### DB Connection

DB接続はDAOに入れる場合もあるみたいですが、参考にさせていただいたソースが別れてたので。

```java:DBConnection.java
package com.hoge;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;

public class DBConnection {
    private Connection con = null;

    // connection
    public Connection getConnection() {
        try {
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "root");
        } catch (SQLException e) {
            System.out.println("DB Connection Error:" + e.getMessage());
        }
        return con;
    }

    // close
    public void close() {
        try {
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            System.out.println("DB Close error.");
        }
    }
}
```

### DAO (Data Access Object)

データへのアクセスと操作。

```java:UserDao.java
package com.hoge;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class UserDao {
    private Connection con;

    public UserDao(Connection con) {
        this.con = con;
    }

    public ArrayList<User> findAll() {
        ArrayList<User> list = new ArrayList<User>();
        try {

            PreparedStatement stmt = con.prepareStatement("select * from users");
            ResultSet rs = stmt.executeQuery();

            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");

                User u = new User(id, name, age);
                list.add(u);
            }

        } catch (SQLException e) {
            System.out.println("Select error.");
        }
        return list;
    }
}
```

### main()

DAO/DTOを利用するメインプログラム。

```java:App.java
package com.hoge;

import java.util.ArrayList;


public class App {
    public static void main(String[] args) {

        DBConnection con = new DBConnection();
        UserDao dao = new UserDao(con.getConnection());

        ArrayList<User> list = dao.findAll();

        list.forEach(user -> System.out.println(user.getId() + " " + user.getName() + " " + user.getAge()));
    }
}
```

### 実行

vscodeのjava extensionの実行を利用しているが、下記ので実行可能。

```bash
mvn -q compile exec:java -Dexec.mainClass=com.hoge.App
```

こんな感じ。

```bash
1 hoge 11
2 foo 22
```