4 min read

SchemaSpy HTMLレポートの日本語の文字化けを解決する方法

SchemaSpy HTMLレポートの日本語の文字化けを解決する方法

概要

データベースやDDLを基にテーブル定義やEntity Ralationship図(以下ER図)を出力したいモチベーションがあるとする。DDLに日本語が含まれているとき、HTMLドキュメントを生成すると、日本語部分が文字化けする。このドキュメントを読むことで、HTMLドキュメントの日本語の文字化けを解決することができます。

前提条件

SchemaSpyとは、データベースからスキーマ定義やER図をレポート形式で出力するソフトウェアです。レポートはHTML形式をサポートしており、インタラクティブで分かりやすくチームに共有することができます。

SchemaSpy • Database Documentation Built Easy.

検証ではDocker Composeで環境を構築しています。

  • Docker Compose version 2.4.1
  • SchemaSpy version 6.1
  • MySQL version 5.7

データベースはサンプルを作成しています。オンラインストアの会員 - 商品 - 注文を表現しています。

CREATE TABLE customers (
    customer_id VARCHAR(36),
    first_name VARCHAR(18) NOT NULL,
    last_name VARCHAR(18) NOT NULL,
    PRIMARY KEY (customer_id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT='会員';

CREATE TABLE products (
    product_id VARCHAR(36),
    name VARCHAR(255) NOT NULL,
    PRIMARY KEY (product_id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT='商品';

CREATE TABLE sales_orders (
    sales_order_id INT AUTO_INCREMENT,
    customer_id VARCHAR(36),
    PRIMARY KEY (sales_order_id),
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT='注文';

CREATE TABLE sales_order_items (
    sales_order_item_id INT AUTO_INCREMENT,
    parent_id INT,
    product_id VARCHAR(36),
    PRIMARY KEY (sales_order_item_id),
    FOREIGN KEY (parent_id) REFERENCES sales_orders(sales_order_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT='注文商品';

online_store_database.sql

再現

docker composeコマンドからSchemaSpyのHTMLレポートを出力します。

$ docker compose up

HTMLレポートはoutputディレクトリに出力されます。HTMLファイルを確認すると日本語に対応した言葉が文字化けしています。

SchemaSpy - HTML Report

調査/原因

MySQLコンテナに接続し調査します。

テーブルのコメントは日本語です。

mysql> SHOW TABLE STATUS;
+-------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------+
| Name              | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment      |
+-------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------+
| customers         | InnoDB |      10 | Dynamic    |    0 |              0 |       16384 |               0 |            0 |         0 |           NULL | 2022-07-31 06:22:03 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | 会員       |
| products          | InnoDB |      10 | Dynamic    |    0 |              0 |       16384 |               0 |            0 |         0 |           NULL | 2022-07-31 06:22:03 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | 商品       |
| sales_order_items | InnoDB |      10 | Dynamic    |    0 |              0 |       16384 |               0 |        32768 |         0 |              1 | 2022-07-31 06:22:03 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | 注文商品 |
| sales_orders      | InnoDB |      10 | Dynamic    |    0 |              0 |       16384 |               0 |        16384 |         0 |              1 | 2022-07-31 06:22:03 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | 注文       |
+-------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+--------------+
4 rows in set (0.00 sec)

文字セットについて確認します。システム変数のクライアントの文字セットが異なるため、文字化け発生していると仮定しました。

mysql> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)

MySQL 接続文字セットおよび照合順序

解決策

オプションファイルから文字セットを更新する

MySQLのオプションファイル(構成ファイル)から文字セットを更新します。

my.cnfファイルを追加してMySQLコンテナの構成ディレクトリにマウントします。

$ mkdir mysql/custom
$ touch mysql/custom/my.cnf
...

  db:
    image: mysql:5.7
    volumes:
      - ./mysql/custom:/etc/mysql/conf.d
...
docker-compose.yaml
[mysql]
default-charset-set=utf8
my.cnf
mysql> SHOW VARIABLES LIKE 'CHARACTER_%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'COLLATION_%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)

接続文字セットおよび照合順序

DDLに文字セットの更新を含める

セッションシステム変数を文字セットに更新することで対応します。SET NAMES ステートメントで実現できます。このステートメントは、character_set_clinet、character_set_connectionおよびcharacter_set_resultの3つのセッションシステム変数を特定の文字セットに設定できます。

SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';

CREATE TABLE customers (
    customer_id VARCHAR(36),
    first_name VARCHAR(18) NOT NULL,
    last_name VARCHAR(18) NOT NULL,
    PRIMARY KEY (customer_id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT='会員';

...

SET NAMES ステートメント

まとめ

クライアント側の文字セットを更新することで、日本語文字化けに対応することができました。完全なコードは以下に公開しています。

GitHub - Umizoko/export-html-report-using-schemaspy
Contribute to Umizoko/export-html-report-using-schemaspy development by creating an account on GitHub.