EclipseでGitの作成者、コミッターの初期設定を変更する

EclipseでGitを使用するとき、作成者、コミッターの欄に、OSのユーザー、コンピューター名が設定されてしまう。コミットする度に修正するのは面倒なので、最初からほしい名称が表示されるようにしたい。

Eclipseの設定のGit関連の設定項目の中から「構成」を選択する。エントリーの追加をクリックし、以下の項目を追加する。

user.name

user.email

Eclipseを一度再起動すると、先ほど設定した値が作成者、コミッターの欄に表示されるようになる。

Window 11でのドラッグアンドドロップの問題

※2022/10/28追記 Window Updateにより、タスクバーへのドラッグアンドドロップが出来るようになりました。

Window 11での問題

隠れていたり、最小化されているWindowにドロップしたい場合、Windows 10まではタスクバーにドラッグして、アプリやWindowのアイコンに重ねれば、それがアクティブになって、前面に表示されるので問題はなかった。

Windows 11ではファイルを掴んだ状態でタスクバーにもっていっても、タスクバーのアプリやWindowがアクティブにならず、ファイルをドロップすることができない。

これはバグではなく、Windows 11の仕様らしいので、今後出来るようになる可能性は低い。新しいやり方に慣れていく必要があるのかもしれない。

Window 11でのやり方

ファイルを掴んだ状態で、「Alt」+「Tab」キーを押す。そうすると実行中のアプリ、開いているWindowの一覧が表示されるので、「Alt」キーを押したまま、「Tab」キーを押し、一覧の選択を切り替える。必要なWindowが選択されたら、「Alt」キーを離す。

選択されていたWindowがアクティブになり、前面に表示されるので、ファイルをドロップすることができるようになる。

Log4jからLogbackに変更する

やりたいこと

色々バグのあったLog4jのログ出力部分のみを、Logbackに変更する。ソースコードには変更が入らないように移行する。

変更前

下記の例ではLog4j-core-2.18.0.jarが読み込まれて、ログ出力を行っている。

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.18.0</version>
        </dependency>

Javaコードは下記のように記述されている。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class SampleImpl {
    private static final Logger log = LogManager.getLogger(SampleImpl.class);

変更後

依存関係にlogback-classic、logback-coreを追加する。log4j-slf4j-implをlog4j-to-slf4jに変更する。

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.18.0</version>
        </dependency>

これで、logback-core-1.4.1.jarでログが出力されるようになる。Javaコードがコンパイルエラーになることもない。

Stable DiffusionをWSL上のUbuntu22.04で動かす

環境

Windows 11
WLS2
Ubuntu 22.04
Python 3.10.4

Hugging Faceのアカウント作成

Hugging Faceのアカウント作成し、Tokenを取得する。ユーザーの設定画面のAccess Tokenを開き、New tokenをクリックしてTokenを作成する。後で使用するためコピーしておく。※Email認証がまだの場合はボタンが非活性になっているので注意

作成時の名前は適当で良い。

インストール

pip install diffusers==0.2.4 transformers scipy ftfy

実行

下記の通り実行し、Tokenを入力する。

$ huggingface-cli login

        _|    _|  _|    _|    _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|_|_|_|    _|_|      _|_|_|  _|_|_|_|
        _|    _|  _|    _|  _|        _|          _|    _|_|    _|  _|            _|        _|    _|  _|        _|
        _|_|_|_|  _|    _|  _|  _|_|  _|  _|_|    _|    _|  _|  _|  _|  _|_|      _|_|_|    _|_|_|_|  _|        _|_|_|
        _|    _|  _|    _|  _|    _|  _|    _|    _|    _|    _|_|  _|    _|      _|        _|    _|  _|        _|
        _|    _|    _|_|      _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|        _|    _|    _|_|_|  _|_|_|_|

        To login, `huggingface_hub` now requires a token generated from https://huggingface.co/settings/tokens .
        
Token: 
Login successful
Your token has been saved to /home/ユーザーID/.huggingface/token

Hugging Faceにログインし、以下のページにアクセスして、Access repositoryをクリックする。
https://huggingface.co/CompVis/stable-diffusion-v1-4

cudaの設定が面倒なので、今回はcudaなしで実行する。

from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", use_auth_token=True)

prompt = "a photograph of an astronaut riding a horse"

image = pipe(prompt)["sample"][0]

image.save("horse.png")

image

実行結果

Hibernate Search 6でFacetを作成したい

初めに

Hibernate Searchを使用して、キーワードに登場する単語の回数を集計したい。※例)残酷な描写あり: 873, 異世界: 481, ハーレム: 471

Hibernate 5まではFacet専用の機能が実装されていたのだが、Hibernate 6からはAggregation機能が実装され、より一般的な集計処理となった。

実装例

集計を実施したいエンティティの変数に下記のようにアノテーションを追加する。

@KeywordField(name = "keyword_facet", aggregable = Aggregable.YES)

集計処理

@Transactional
public Map<String, Long> aggregateByKeywords() {
    AggregationKey<Map<String, Long>> countsByKeywordKey = AggregationKey.of("countsByKeyword");

    return Search.session(entityManager)
            .search(Novel.class) // エンティティ
            .where(f -> f.matchAll()) // 全検索
            .aggregation(countsByKeywordKey, f -> f.terms()
                    .field("keyword_facet", String.class)
                    .maxTermCount(10)) // 登場回数の多い順10件まで
            .fetch(10)
            .aggregation(countsByKeywordKey);
}

集計結果

Mapにキーワードとその文字の登場回数が設定されているので、Loop処理等で展開する。以下はVueの実装例。

<span v-for="(value, name, index) in aggregateByKeywords" :key="index">
    <span v-if="index > 0">, </span>
    {{ name }}: {{ value }}
</span>

R15: 1074, 残酷な描写あり: 873, 異世界: 481, ハーレム: 471, ファンタジー: 451, 異世界転移: 389, チート: 378, 魔法: 362, 冒険: 319, 主人公最強: 296

Hibernate ORMとHibernate Searchで検索結果をソートする

備忘録として、いくつかの実装例を記載しておく。

Hibernate ORMのソート(Spring Data JPAを使用する)

Spring Bootを使用していなくても、下記のように依存関係を読み込むことでSpring Data JPAを使用できる。

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>${spring-data.version}</version>
</dependency>

クエリメソッドを使用する

ルールに沿ったメソッド名を使用することにより、自動的にHibernateへSQLが発行される。

public interface CrudRepository<T, ID> extends Repository<T, ID> {
    // 登録、または更新
    <S extends T> S save(S entity);      
    // プライマリーキーで検索
    Optional<T> findById(ID primaryKey); 
    // 全検索
    Iterable<T> findAll();               
    // 全件数
    long count();                        
    // 削除
    void delete(T entity);               
    // 存在チェック
    boolean existsById(ID primaryKey); 

例えば、小説データを全検索して、小説のタイトルでソートをかけたい場合、下記のように書く。複数のソート条件を指定する場合は続けて記載する。

@Repository
public interface NovelRepository extends JpaRepository<Novel, Long>, JpaSpecificationExecutor<Novel> {
    List<Novel> findAllByOrderByTitle();
}

※「findAll」の後に余分な「By」があるのは、ルール的にそこに検索条件が入ることになるため、今回は全検索なので「By」だけが残っている。

条件 APIを使用する

criteria を記述することにより、クエリの where 句を定義している場合、ソートは以下のように定義する。複数のソート条件を指定する場合は引数を追加する。

novelRepository.findAll(spec, JpaSort.by("title"))
@Repository
public interface NovelRepository extends JpaSpecificationExecutor<Novel> {
}

Hibernate Searchのソート

ソートの処理実装前に、エンティティに@KeywordFieldを追記する必要がある。

    /** タイトル */
    @FullTextField(analyzer = "japanese")
    @KeywordField(name = "titleSort", sortable = Sortable.YES)
    private String title;

検索時に上記で定義した名称をソート条件に指定する。

import org.hibernate.search.mapper.orm.Search;

@Service
public class NovelService {
    private final EntityManager entityManager;

    @Transactional
    public List<Novel> findAllIndex() {
        return Search.session(entityManager)
                .search(Novel.class)
                .where(f -> f.matchAll())
                .sort(f -> f.field("titleSort"))
                .fetchAllHits();
    }

ソートの条件を指定していないときは、スコアの高い順にソートされている。大雑把に言えば、スコアが高いほど、より多くの述語にマッチしているか、より良くマッチしていることを意味する。そのため、Hibernate Searchに関しては明示的にソートの条件を指定しない方が、良いのかもしれない。

Vue3でvue-i18nの初期化でエラーになる

以下のようなエラーが出ていた。

Uncaught (in promise) SyntaxError: Not available in legacy mode
    at createCompileError (message-compiler.esm-bundler.js?965a:54:1)
    at createI18nError (vue-i18n.esm-bundler.js?666d:100:1)
    at useI18n (vue-i18n.esm-bundler.js?666d:2228:1)
    at setup (NovelSearch.vue?0b40:12:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
    at setupStatefulComponent (runtime-core.esm-bundler.js?d2dd:7165:1)
    at setupComponent (runtime-core.esm-bundler.js?d2dd:7119:1)
    at mountComponent (runtime-core.esm-bundler.js?d2dd:5473:1)
    at processComponent (runtime-core.esm-bundler.js?d2dd:5448:1)
    at patch (runtime-core.esm-bundler.js?d2dd:5038:1)

Vue 3のsetupでuseI18nを構成する場合は、createI18nのlegacyオプションをfalseに設定する必要がある。

const i18n = createI18n({
  legacy: false, // you must set `false`, to use Composition API
  locale: 'ja',
  messages: {
    en: enNames,
    ja: jaNames
  }
});

const app = createApp(App)
app.use(i18n)
app.mount('#app')

参考:https://vue-i18n.intlify.dev/guide/advanced/composition.html

Eclipseで特定のWarningを非表示にしたい

現象

Eclipseでは属性名の間違い等を警告してくれる便利な機能があるが、新しい属性名に対応していないことがあり、正しい値なのにWarningが出てしまうことがある。

下記の例だと、「integrity」、「crossorigin」、「referrerpolicy」が未定義とWarningが出てしまっている。

Warningを非表示にする方法

  1. プロジェクトのプロパティから、検証のHTML構文を開く。
  2. 「プロジェクト固有の設定を可能にする」にチェックを入れる。
  3. 「指定された属性名を検証で無視」にチェックを入れる。
  4. 無視する属性名をカンマ区切りで入力する。

結果

下記の通りWarningは表示されなくなった。

Raspberry Pi 4のBiosは表示されるがOSが起動しない

Raspberry Pi 4のBiosは表示されるがOSが起動しない問題が発生した。

SSDの破損、モニタとの相性等確認したが問題なしで、確認を進めた結果、原因は電源供給のUSBアダプタにあった。

最近下記のUSBアダプタを購入したので、それをRaspberry Piの電源に使用したところ、今回の現象が発生した。Biosは表示されるがOSが起動する段階になるとRaspberry Piの電源が落ちてしまう。

下記の少し古いモデルに変更すると問題なくRaspberry OSが起動した。

USBケーブル等全て同じにして、USBアダプタのみの変更で問題が解決したので、おそらくUSBアダプタとの相性に問題があったのだと思う。

Local-Variable Type Inference ローカル変数宣言型推論

Java 10から、型の宣言を「var」で置き換えて省略することが出来るようになった。例えば、下記のように、

        var context = new ClassPathXmlApplicationContext(CONFIG_LOCATION);

        try (var stockFile = Files.newBufferedReader(Paths.get("src/stock1.txt");) {
        for (var i = 0; i < args.length; i++) {
        var executeFlag = true;

と記述することが出来る。積極的に使った方が良いか悩む。

桁あふれの心配をしなくて良いので、for分の初期化式の型宣言には便利かもしれない。