Yarnをインストールする(v3系)

過去にYarnを使っていましたが、最近は全然使用していませんでした。ふと使おうかと思ったのですが、インストール方法がだいぶ変わっており、初めてインストールを行う人やしばらくぶりにインストールをしようとすると手順に戸惑いそうだったので、基本的なインストール手順をまとめました。

前提条件

まずは記事執筆時点でのLTSバージョンである18.16.0を使用してインストールを行います。

$ node -v
v18.16.0
$ npm -v
9.6.6

npmについても執筆時点の最新バージョンにアップデートしています。

手順はmacOS上で確認していますが、特にシェルコマンドなどは使っていないので、どの環境でも同様の手順でインストール可能です。

また、インストール手順は公式の手順に準じて進めます。

公式の手順で十分な方はそちらを参照してください。

corepackを有効化する

corepacknpmyarnなどのパッケージマネージャを管理するツールです。デフォルトでは有効になっていないため有効します。

$ corepack enable

以前はnpmコマンドでインストールしていましたが、今はcorepackでインストールします。npm install yarnでもインストールできるのですが、v1系がインストールされるため、最新バージョンをインストールしたい場合はcorepackコマンドを使用する必要があります。

yarnをインストールする

次にcorepack を使ってyarnをインストールします。執筆時点では3.5.1が最新版のようですので、3.5.1をインストールすることにします。

yarnリポジトリはv1系のリポジトリとなっているのでご注意ください。

corepack prepareコマンドでインストールと有効化を行います。

$ corepack prepare yarn@3.5.1 --activate
Preparing yarn@3.5.1 for immediate activation...

Node.jsをasdfでインストールしている場合は、追加で以下のコマンドを実行してyarnコマンドを使用できるようにします。

$ asdf reshim

指定したバージョンがインストールできていることを確認します。

$ yarn -v
3.5.1

これでインストールが完了しました。

package.jsonを作成する

ついでにyarnコマンドを使ってpackage.jsonを作成してみましょう。

$ yarn init -y
{
  name: 'test',
  packageManager: 'yarn@3.5.1'
}

corepackの管理下にあるパッケージマネージャを使ってpackage.jsonを作成すると、packageManagerというプロパティが追加されるようになります。これがあるとyarn以外のパッケージマネージャを使用するとエラーが出るようになります。

Apple Silicon MacにStable Diffusion WebUIをインストールする

Stable DiffusionをApple SiliconのmacOSにインストールしてみましたが、少しコツが必要でした。

インストール時期やApple Siliconの種類によっては若干変わるかもしれませんが、私がM1 Maxチップ搭載のMacBook Proで成功した手順をまとめてみました。

必要なパッケージをインストールする

こちらは公式に従ってインストールします。私の環境では最終的にPythonはここでインストールしたものではなく、Asdfで導入したものを使用しているので、3.10系であればここでインストールしなくてもよいと思われます。

brew install cmake protobuf rust python@3.10 git wget

Stable Diffusion WebUIをダウンロードする

GithubのReleasesでもダウンロードできそうですが、macOSの場合はリポジトリをクローンする必要があります。

任意のディレクトリにリポジトリをcloneしてください。

git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui

追加データをダウンロードする

手順の中でここが一番面倒かもしれません。ここでは執筆時点最新のv2.1を使用します。

上記サイトからvae-ft-mse-840000-ema-pruned.ckptというファイルをダウンロードし 、stable-diffusion-webui/models/Stable-difusionに保存してください。

保存後、ファイル名をv2-1_768-ema-pruned.vae.ptに変更してください。

上記サイトからv2-1_768-ema-pruned.safetensorsというファイルをダウンロードし、stable-diffusion-webui/models/Stable-difusionに保存してください。

ここを開いて、表示された内容をコピーし、stable-diffusion-webui/models/Stable-difusionv2-1_768-ema-pruned.yamlというファイル名で保存してください。

Stable Diffusion WebUIを起動する

cd stable-diffusion-webui
./webui.sh

起動すると、以下のようなログが表示されます。URLが出ているので、ここにアクセスしてください。

Model loaded in 3.6s (load weights from disk: 0.3s, create model: 0.2s, apply weights to model: 1.8s, apply half(): 0.6s, load VAE: 0.1s, move model to device: 0.5s).
Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.
Startup time: 11.2s (import torch: 2.1s, import gradio: 1.7s, import ldm: 0.4s, other imports: 2.9s, load scripts: 0.3s, load SD checkpoint: 3.6s, create ui: 0.2s).

ブラウザでアクセスすると、以下のような画面が表示されます。

設定変更を行う

同じようにApple Silicon Macにインストールしている方の記事で、この点に触れていない方も結構見かけるので、もしかすると環境依存かもしれませんが、私の環境ではv2.1でGenerateしようとすると以下のようなエラーが表示されました。

  0%|                                                                                                                                                                                                                                    | 0/20 [00:02<?, ?it/s]
Error completing request
Arguments: ('task(6gvckovujc9xon0)', 'sailing ship', '', [], 20, 0, False, False, 1, 1, 7, -1.0, -1.0, 0, 0, 0, False, 512, 512, False, 0.7, 2, 'Latent', 0, 0, 0, [], 0, False, False, 'positive', 'comma', 0, False, False, '', 1, '', 0, '', 0, '', True, False, False, False, 0) {}
Traceback (most recent call last):
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/call_queue.py", line 56, in f
    res = list(func(*args, **kwargs))
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/call_queue.py", line 37, in f
    res = func(*args, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/txt2img.py", line 56, in txt2img
    processed = process_images(p)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 503, in process_images
    res = process_images_inner(p)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 653, in process_images_inner
    samples_ddim = p.sample(conditioning=c, unconditional_conditioning=uc, seeds=seeds, subseeds=subseeds, subseed_strength=p.subseed_strength, prompts=prompts)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/processing.py", line 869, in sample
    samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, image_conditioning=self.txt2img_image_conditioning(x))
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 358, in sample
    samples = self.launch_sampling(steps, lambda: self.func(self.model_wrap_cfg, x, extra_args={
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 234, in launch_sampling
    return func()
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 358, in <lambda>
    samples = self.launch_sampling(steps, lambda: self.func(self.model_wrap_cfg, x, extra_args={
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/venv/lib/python3.10/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
    return func(*args, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/repositories/k-diffusion/k_diffusion/sampling.py", line 145, in sample_euler_ancestral
    denoised = model(x, sigmas[i] * s_in, **extra_args)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/venv/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1130, in _call_impl
    return forward_call(*input, **kwargs)
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/sd_samplers_kdiffusion.py", line 152, in forward
    devices.test_for_nans(x_out, "unet")
  File "/Users/t0k0sh1/Workspace/stable-diffusion-webui/modules/devices.py", line 152, in test_for_nans
    raise NansException(message)
modules.devices.NansException: A tensor with all NaNs was produced in Unet. This could be either because there's not enough precision to represent the picture, or because your video card does not support half type. Try setting the "Upcast cross attention layer to float32" option in Settings > Stable Diffusion or using the --no-half commandline argument to fix this. Use --disable-nan-check commandline argument to disable this check.

ちなみに、v1.4やv1.5ではこの事象は起きなかったので、v2.x系固有のエラーかもしれません。

これを解消するために、設定変更を行います。画面上部のタブからSettingsを選択し、

左のメニューからStable Diffusionを選択します。

バージョンにもよるかもしれませんが、一番下にUpcast cross attention layer to float32というチェックボックスがあるので、ここにチェックをつけてください。

最後に設定を反映させるため、画面上部のApply settingsボタンを押してください。

これでエラーが出ずに画像生成ができるようになります。

気になった話題のまとめ(2023/04/11)

M3チップが出るんじゃないかという噂も出ていますが、こんなハイペースで出されるといつで買おうか迷いますよね。

私もしばらくは買わないと思いますが、持ち運びしやすい13インチMacBook Airはどこかのタイミングで買いたいなと思っています。

最初、「新しいモバイルモニターか」と思っていましたが、よくよく読んでみるとモバイルモニターを縦置きするためのスタンドでした。価格的には3千円程度と手頃な価格ですので、モバイルモニターを使っている方にはお勧めできそうです。

ただ、ベニア板などから切り出せる人からすると自分で作ったほうが早いかもしれません。

気になった話題のまとめ(2023/04/07)

Tailwind CSSの拡張機能、結構増えているんですね。本記事では以下の4つの拡張機能を紹介していますが、tailwindで検索すると、他にも星5の拡張機能はたくさんありました。拡張機能パックでも他の拡張機能がパックされていたりするので、自分に合う拡張機能が他にもあるかもしれません。

気になった話題のまとめ(2023/04/06)

折りたたみ機能は昨今のエディタやIDEには大抵備わっていますが、それをより見やすくするVS Codeの拡張機能です。

折り畳んだ行数が表示されるのと、閉じブラケットも折りたたんでくれるので、より見やすくよりわかりやすくなります。

ショートカットを覚えられたら使いやすいんだろうなとは思いますし、コードを綺麗に保つことでより可読性が向上することが見込めるので、これを機に使ってみようと思います。

気になった話題のまとめ(2023/04/05)

ChatGTPに関する話題

ChatGPT、使っていますか?

私は仕事では結構使っているのですが、正直普段の生活ではあまり活用してきませんでした。

ふと目に入った知らない言葉を説明してもらう、というのであれば確かに普段の生活でも使えそうです。仕事で使っていると、最終的に正しいかどうかを検証するようにしているためか、レシピとかを生成するのはちょっと抵抗がありますね。

ChatGPTを活用したいけど、自社の情報を学習したことによってどこかで流出したらどうしよう、自社や業界に特化して学習してほしいという要望は多いと思います。

ただ、自社で運用するにはコストが高すぎる、そういったことを叶えるサービスになります。これからもこういったサービスは出てくると思いますが、クラウドベンダーからも提供されるのも時間の問題だと思います。

低価格化が進むだけでなく、ChatGPTのミドルウェア化、サービス化が加速していきそうです。

いくつか入れていますが、注意点としては自動から手動へ設定を変えたほうがいいということです。自動は楽ですが、ChatGPTのログがどんどん残るので使いたい時に限定して使ったほうがいいです。

直接ChatGPTに聞いた内容が流れていってしまっては元も子もないですからね。ログを外部に出力して検索できるようなサービスが出てくれば自動でもいいと思いますね。

[Pandas]代表値を求める(平均値、中央値、最頻値)

一般的によく知られている代表値といえば、平均値(mean)、中央値(median)、最頻値(mode)です。

Pandasを使ってこれらの値を求めてみます。

下準備

今回はTitanicデータセットから年齢(Age)を使用します。

import pandas as pd
import math

df = pd.read_csv('./titanic/train.csv')

平均値を求める

平均値を求めるにはmean()を使用します。

# 平均値(mean)を求める
df['Age'].mean()
# -> 29.69911764705882

中央値を求める

中央値を求めるにはmedian()を使用します。

# 中央値(median)求める
df['Age'].median()

最頻値を求める

最頻値を求めるには一工夫が必要です。最頻値は最も大きい度数の階級値になるため、一旦度数分布表を作成します。

ヒストグラムを確認する

度数分布表を作成する前にヒストグラムを確認しておきましょう。

df['Age'].hist(bins=10)

ビンの数を10に設定してヒストグラムを作成すると、20代が最頻値のようだということがわかります。

最頻値を求める

視覚的に確認できたところで、最頻値を求めます。度数分布表の作成方法はいくつかありますが、ここでは簡易的にcut()value_counts()を組み合わせて、先ほど確認したグラフと同じ区間で度数分布表を作成します。

# 度数分布表を作成する
pd.cut(df['Age'], 10).value_counts()
---
(16.336, 24.294]    177
(24.294, 32.252]    169
(32.252, 40.21]     118
(40.21, 48.168]      70
(0.34, 8.378]        54
(8.378, 16.336]      46
(48.168, 56.126]     45
(56.126, 64.084]     24
(64.084, 72.042]      9
(72.042, 80.0]        2
Name: Age, dtype: int64

作成した結果を確認しても20代が最頻値のようです。最頻値は区間の最小値と最大値の中間になりますので、$24.294-(24.294-16.336)\div2=20.315$となります。

[Oracle]WITH句で階層問い合わせを行う

OracleではWITH句を使って階層問い合わせを行うことができます。

サンプルデータ

説明として、階層を持つフォルダを管理するFOLDER_TBLとフォルダに格納するファイルを管理するFILE_TBLを用意します。

CREATE TABLE FOLDER_TBL (
  FOLDER_ID NUMBER(10) NOT NULL,
  PARENT_ID NUMBER(10),
  FOLDER_NAME VARCHAR2(255) NOT NULL,
  PRIMARY KEY (FOLDER_ID),
  FOREIGN KEY (FOLDER_ID) REFERENCES FOLDER_TBL(FOLDER_ID) ON DELETE CASCADE
);

FOLDER_TBLはフォルダを識別するためのFOLDER_IDとあるフォルダとその上位フォルダを紐づけるためのPARENT_IDを持っています。PARENT_IDは最上位フォルダの場合はNULLになります。

CREATE TABLE FILE_TBL (
  FILE_ID NUMBER(10) NOT NULL,
  FOLDER_ID NUMBER(10) NOT NULL,
  FILE_NAME VARCHAR2(255) NOT NULL,
  FILE_SIZE NUMBER(10),
  PRIMARY KEY (FILE_ID),
  FOREIGN KEY (FOLDER_ID) REFERENCES FOLDER_TBL(FOLDER_ID) ON DELETE CASCADE
);

ファイルはFILE_IDによって識別され、格納先のフォルダに紐づけるためのFOLDER_IDを持っています。FOLDER_IDNULLになることはなく、必ずどこかのフォルダに紐づきます。

-- FOLDER_TBLテーブルにデータを登録するSQL
INSERT INTO FOLDER_TBL (FOLDER_ID, parent_id, FOLDER_NAME) VALUES (1, NULL, 'Folder 1');
INSERT INTO FOLDER_TBL (FOLDER_ID, parent_id, FOLDER_NAME) VALUES (2, 1, 'Folder 1-1');
INSERT INTO FOLDER_TBL (FOLDER_ID, parent_id, FOLDER_NAME) VALUES (3, NULL, 'Folder 2');

-- FILE_TBLテーブルにデータを登録するSQL
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (1, 1, 'file1.txt', 100);
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (2, 1, 'file2.txt', 200);
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (3, 2, 'file3.txt', 150);
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (4, 2, 'file4.txt', 300);
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (5, 3, 'file5.txt', 50);
INSERT INTO FILE_TBL (FILE_ID, FOLDER_ID, FILE_NAME, FILE_SIZE) VALUES (6, 3, 'file6.txt', 250);

サンプルデータを用意しました。

FOLDER_TBLは以下のようなデータとなっています。最上位階層は二つ、うち一つにはサブフォルダがあります。

FOLDER_IDPARENT_IDFOLDER_NAME
1NULLFolder 1
21Folder 1-1
3NULLFolder 2

FILE_TBLは以下のようなデータになっています。各フォルダに2ファイルずつファイルが格納されています。

FILE_IDFOLDER_IDFILE_NAMEFILE_SIZE
11file1.txt100
21file2.txt200
32file3.txt150
42file4.txt300
53file5.txt50
63file6.txt250

下層から上層に向かって階層問い合わせをする

あるファイルを指定し、その格納フォルダから最上位フォルダまでの階層を取得してみます。ここではサブフォルダにあるfile3.txtが格納されているフォルダから上位フォルダへ向かって階層問い合わせを行います。

WITH FOLDER_HIERARCY (
    FOLDER_ID,
    PARENT_ID,
    FOLDER_NAME,
    FOLDER_PATH
) AS (
  -- 最下層のフォルダ
  SELECT
    FOLDER_ID,
    PARENT_ID,
    FOLDER_NAME,
    FOLDER_NAME FOLDER_PATH
  FROM
    FOLDER_TBL FD1
  WHERE
    -- フォルダに格納されているファイルのファイル名が'file3.txt'
    EXISTS(SELECT 1 FROM FILE_TBL FL1 WHERE FD1.FOLDER_ID = FL1.FOLDER_ID AND FL1.FILE_NAME = 'file3.txt')
  UNION ALL
  SELECT
    FD2.FOLDER_ID,
    FD2.PARENT_ID,
    FD2.FOLDER_NAME,
    FD2.FOLDER_NAME || ' / ' || BASE.FOLDER_PATH
  FROM
    FOLDER_HIERARCY BASE -- このテーブルに対して
    INNER JOIN FOLDER_TBL FD2 -- このテーブルを結合していく
    ON
      BASE.PARENT_ID = FD2.FOLDER_ID -- 下位フォルダのPARENT_IDに一致するFOLDER_IDのフォルダは1つ上位のフォルダとなる
)
SELECT
  FOLDER_PATH || ' / file3.txt'
FROM
  FOLDER_HIERARCY
WHERE
  PARENT_ID IS NULL -- PARENT_IDがNULLのレコードに絞り込むと最上位フォルダまでのパスが得られる
;

ポイントは、

  • 階層問い合わせをするときは項目を明示する(しないとエラーになる)
  • 基準となるレコードに対して上位のレコードを結合していく

です。下層から上層に向かって階層問い合わせする場合は、基準となるテーブル(BASE)の親IDと一つ上位となるテーブル(FD2)のIDを結合する点に気をつけましょう。

上層から下層に向かって階層問い合わせをする

同じことを逆からやってみましょう。

WITH FOLDER_HIERARCY (
    FOLDER_ID,
    PARENT_ID,
    FOLDER_NAME,
    FOLDER_PATH
) AS (
  -- 最上層のフォルダ
  SELECT
    FOLDER_ID,
    PARENT_ID,
    FOLDER_NAME,
    FOLDER_NAME FOLDER_PATH
  FROM
    FOLDER_TBL FD1
  WHERE
    FD1.PARENT_ID IS NULL
  UNION ALL
  SELECT
    FD2.FOLDER_ID,
    FD2.PARENT_ID,
    FD2.FOLDER_NAME,
    BASE.FOLDER_PATH || ' / ' || FD2.FOLDER_NAME
  FROM
    FOLDER_HIERARCY BASE -- このテーブルに対して
    INNER JOIN FOLDER_TBL FD2 -- このテーブルを結合していく
    ON
      BASE.FOLDER_ID = FD2.PARENT_ID -- 上位フォルダのFOLDER_IDに一致するPARENT_IDのフォルダは1つ下位のフォルダとなる
)
SELECT
  FOLDER_PATH || ' / ' || FILE_NAME
FROM
  FOLDER_HIERARCY T1
  INNER JOIN FILE_TBL T2
  ON
    T1.FOLDER_ID = T2.FOLDER_ID
WHERE
  FILE_NAME = 'file3.txt'
;

上層から下層に向かって階層問い合わせする場合は、基準となるテーブル(BASE)のIDと一つ下位となるテーブル(FD2)の親IDを結合する点に気をつけましょう。

いずれの検索結果もFolder 1 / Folder 1-1 / file3.txtとなります。

[Spring Boot]IntelliJ IDEAでLombokを使っていてエラーになる場合の対処方法

以下の記事に解決方法が載っていました。

https://stackoverflow.com/questions/72583645/compile-error-with-lombok-in-intellij-only-when-running-build

遭遇した事象

Spring Initializrからダウンロードした時点でLombokは依存関係に追加されています。

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.0.4'
	id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.t0k0sh1'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.projectlombok:lombok:1.18.22'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

IntelliJ IDEAでLombokを使用可能にするためには、設定のビルド、実行、デプロイ>コンパイラー>アノテーションプロセッサーで、「アノテーション処理を有効にする」にチェックをつけ、「プロジェクトクラスパスからプロセッサーを取得する」にチェックがついている状態にします。

ここまでがよく知られているLombokの導入方法になります。

lombok.Dataアノテーションを定義したクラスを作成し、

package com.t0k0sh1.tutorial.entity;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
    private String email;
    private String password;
}

自動生成されているであろうgetterを使ってみます。

package com.t0k0sh1.tutorial.controller;

import com.t0k0sh1.tutorial.entity.User;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
public class UserController {
    private final List<User> users = new ArrayList<>();

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return users.stream().filter(a -> a.getId().equals(id)).findFirst().orElse(null);
    }

}

すると、getterが見つからずにコンパイルエラーとなります。

/Users/t0k0sh1/Workspace/tutorial/src/main/java/com/t0k0sh1/tutorial/controller/UserController.java:15: エラー: シンボルを見つけられません
        return users.stream().filter(a -> a.getId().equals(id)).findFirst().orElse(null);
                                           ^
  シンボル:   メソッド getId()
  場所: タイプUserの変数 a

対処方法

build.gradleを以下のように書き換えることで問題を解消することができます。

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.0.4'
	id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.t0k0sh1'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.projectlombok:lombok:1.18.22'
	implementation 'org.modelmapper:modelmapper:3.1.1'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

	// 以下の1行を追加する
	annotationProcessor 'org.projectlombok:lombok:1.18.22'
}

tasks.named('test') {
	useJUnitPlatform()
}

追加でannotationProcessor 'org.projectlombok:lombok:1.18.22'を追記します。(バージョン部分は元の記述に合わせてください)

Gradleプロジェクトの再ロード(右端のGradleタブを開いて更新ボタンをクリックする)し、プロジェクトのビルドを行なってください。

すると、先ほどまでエラーとなっていましたが、今度はビルドに成功します。

[Spring Boot]プロジェクトを作成する(Spring Initializr)

Spring Bootのプロジェクトの作成方法はいくつかありますが、本記事ではSpring Initializrを使って作成します。

Projectを選択する

執筆時点では「Gradle – Groovy」「Gradle – Kotolin」「Maven」から選択できます。使いたいものを選択してください。

ここでは「Gradle – Groovy」を選択しています。

Languageを選択する

執筆時点では「Java」「Kotolin」「Groovy」から選択できます。使いたいものを選択してください。

ここでは「Java」を選択しています。

Spring Bootのバージョンを選択する

Spring Bootのバージョンを選択してください。

ここでは「3.0.4」を選択しています。

Project Metadataを入力する

プロジェクトのメタデータを入力します。

内容はプロジェクトに合わせて設定してください。

Dependenciesを選択する

Dependenciesの選択は任意ですが、Webアプリケーションのプロジェクトを作成するので、Spring Webだけ追加しておきます。すでに使用するものが決まっている場合はそれも追加しておいてください。

プロジェクトをダウンロードする

GENERATEボタンをクリックしてプロジェクトをダウンロードしてください。

プロジェクトを展開・配置してIDEで開く

ではダウンロードしたプロジェクトを展開・配置して、IDEで開いてみましょう。ここではIntelliJ IDEA Ultimateを使用しています。

まずはダウンロードしたZIPファイルを展開し任意のフォルダに配置します。

$ unzip ~/Downloads/tutorial.zip -d ~/Workspace/

次にIDEでプロジェクトを開きます。

動作確認のためにアプリケーションを実行してみましょう。

アプリケーションが起動したらhttp://localhost:8080/にアクセスします。

Spring BootではMainメソッド持ったクラス以外何もないため、表示するページがなく、エラー画面が表示されますが、この画面が表示しているのであれば問題ありません。

[Oracle]ユーザー(スキーマ)を作成する

ローカル環境で使用する開発用・テスト用のユーザーを作成します。

今回使用した環境は以下のとおりです。

  • Oracle Database XE 21c

本記事で実行しているSQLは、すべてSYSTEMユーザーで実行しています。

テーブルスペースを確認する

まずは使用するテーブルスペースを確認します。

-- テーブルスペースを一覧表示する
SELECT TABLESPACE_NAME, INITIAL_EXTENT FROM DBA_TABLESPACES;
TABLESPACE_NAMEINITIAL_EXTENT
SYSTEM65536
SYSAUX65536
UNDOTBS165536
TEMP1048576
USERS65536

ここではDEFAULT TABLESPACEUSERSを使用し、TEMPORARY TABLESPACETEMPを使用します。

ユーザーを作成する

どのテーブルスペースを使用するかが決まったら、ユーザーを作成します。

-- ユーザーを作成する
CREATE USER EXAMPLE IDENTIFIED BY PASSWORD DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP PROFILE DEFAULT;

ここではEXAMPLEというユーザー(スキーマ)をPASSWORDというパスワードで作成しています。

このままではログインすらできないユーザーですので、作成したユーザーに権限を与えます。ここではローカルでの開発用・テスト用のユーザーですので、作成しそうなオブジェクトを作成する権限は一通り与えておきます。

-- ユーザーに権限を与える
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE TRIGGER, CREATE SYNONYM, UNLIMITED TABLESPACE TO EXAMPLE;

作成したユーザー名とパスワードでログインすれば、ユーザー名と同じスキーマが使用可能になっています。

パスワードの有効期限を確認・設定する(オプション)

この手順は必須ではありませんが、念のためパスワードの有効期限を確認しておきます。プロジェクトや職場のポリシーにもよりますが、開発用・テスト用のユーザーですので、パスワードの有効期限切れにはならない方が運用が楽だと思います。

今回使用したプロファイルはDEFAULTですので、DEFAULTプロファイルの有効期限を確認します。

-- DEFAULTプロファイルの有効期限を確認する
SELECT PROFILE, RESOURCE_NAME, RESOURCE_TYPE, LIMIT FROM DBA_PROFILES WHERE RESOURCE_NAME = 'PASSWORD_LIFE_TIME' AND PROFILE = 'DEFAULT';
PROFILERESOURCE_NAMERESOURCE_TYPELIMIT
DEFAULTPASSWORD_LIFE_TIMEPASSWORDUNLIMITED

今回はOracle XEを使用していますが、特に設定変更していない状態でUNLIMITEDになっています。

ここがUNLIMITED以外になっていて、無期限に変更したい場合は以下のSQLを実行します。

-- DEFAULTプロファイルの有効期限を無期限に変更する
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;

SQL実行後に再度確認して、UNLIMITEDになっていることを確認してください。

Apple Silicon MacのDockerでOracle Databaseを動かす

執筆時点(2023/03/01)での暫定的な対応となる点にご注意ください。将来的にはOracle DatabaseがARMに対応する可能性があります。
Oracle DatabaseのARM対応については、以下の動画の26:40 – 27:22をご覧ください。

Oracle Database: What’s new, what’s next

Apple Silicon MacでOracle Databaseを動かす選択肢はいくつかありますが、よく知られている方法は私の環境ではうまく生きませんでした。

ここでは私の環境で成功した方法を共有します。

この方法は、

で紹介されている方法になります。

手順を実行するためには、

  • Homebrew
  • Docker

が必要となります。

Colimaをインストールする

まずはColimaをインストールします。Dockerの--platform linux/x86_64ではうまくいきませんでしたので、ご注意ください。

$ brew install colima

Homebrewでインストールしますので、インストールしていない場合は先にインストールしてください。

次にColimaを起動します。起動するとDockerのコンテキストが変更されます。

$ colima start --arch x86_64 --memory 4

ここでは参考にした記事と同じく4(GB)のメモリを割り当てていますが、必要に応じて増やしてください。

$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                                     KUBERNETES ENDPOINT   ORCHESTRATOR
colima *            moby                colima                                    unix:///Users/user1/.colima/default/docker.sock
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                               swarm
desktop-linux       moby                                                          unix:///Users/user1/.docker/run/docker.sock

現在のコンテキストがcolimaになっていることを確認してください。変更されていない場合は、

$ docker context use colima

で変更してください。

Oracle Databaseを起動する

Oracle DatabaseをDockerで起動します。

$ docker run -d -p 1521:1521 -e ORACLE_PASSWORD=<パスワード> -v oracle-volume:/opt/oracle/oradata gvenzl/oracle-xe

<パスワード>部分は任意のパスワードを設定してください。このパスワードはSYSユーザーとSYSTEMユーザーのパスワードになります。

例えば、パスワードをpasswordにした場合は以下のようになります。

$ docker run -d -p 1521:1521 -e ORACLE_PASSWORD=password -v oracle-volume:/opt/oracle/oradata gvenzl/oracle-xe

すぐに制御が返ってきますので、少し経ったら接続してみましょう。ローカルにSQL*Plusはインストールされていないと思いますので、何かしらのデータベース接続ツールを使用してください。

私はDataGripを使って接続しています。ユーザーはsystem、パスワードは先ほど起動時に設定したパスワードを入力してください。

まとめ

恐らくこれが現状では最も簡単にApple Silicon MacでOracle Databaseを動作させる方法だと思います。将来的にはVirtualBoxなどでもっと簡単にOracle Databaseを動作させることができるようになる可能性がありますので、暫定的な対応とお考えください。

モバイルバージョンを終了