TIL

Today I Learned. 知ったこと、学んだことを書いていく

【Hibernate】NativeQuery.setProperties でパラメータのセットにPOJOを使う

hibernateSQL実行時のパラメータセットPOJOが使えたのが便利そうだからメモっておく

org.hibernate.query.NativeQuery.setProperties()を使うことでパラメータのセットにPOJOが使える

// Dao.java
@Override
public void insert(People people) {
    Session session = sessionFactory.getCurrentSession();
    NativeQuery query = session.createNativeQuery("insert into people (first_name, last_name, division_id) values (:firstName, :lastName, :divisionId)");
    query.setProperties(people);
    query.executeUpdate();
}
// People.java
@Data
public class People {
    private String firstName;
    private String lastName;
    private Integer divisionId;
}
//Service.java
@Override
@Transactional
public void insertUser() {
    People people = new People();
    people.setFirstName("taro");
    people.setLastName("yamada");
    peopleDao.insert(people);
}

:フィールド名としたら、自動でマッピングしてくれた

NULLが許可されているカラムに対応するフィールドがnullの場合、nullをINSERTしてくれた

 +-----------+------------+-----------+-------------+
 | person_id | first_name | last_name | division_id |
 +-----------+------------+-----------+-------------+
 | 1         | first      | last      | <null>      |
 +-----------+------------+-----------+-------------+

参考文献

【Java】Spring Bootで Java Config を使用し、Propertiesファイルを読み込む

SpringBootを使って、Propertiesファイルを読みたかったから、やってみた

XML書きたくないから、Java Configで実装した

以下の2つのJavaクラスを作った

  • sample/App.java
  • sample/config/Config.java

sample/config/Config.java

package sample.config;

import java.io.IOException;
import java.util.Properties;

import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableAutoConfiguration
public class Config {

    @Bean
    public Properties sqlProperties() throws IOException {

        PropertiesFactoryBean propFactoryBean = new PropertiesFactoryBean();
        propFactoryBean.setLocation(new ClassPathResource("sample.properties"));
        // これ大事!
        propFactoryBean.afterPropertiesSet();
        return propFactoryBean.getObject();

    }
}
  • Propertiesを返すBeanを定義
  • Propertiesを生成するためのPropertiesFactoryBeanを用意
    • locationClassPathResourceインスタンスをセット
      • src/main/resources/sample.propertiesだとしたら、new ClassPathResource('sample.properties')とする
      • SpringBootでsrc/main/resourcesはクラスパス内のため
    • PropertiesFactoryBean.afterPropertiesSet()がないとうまく値を取れなかったため、必ず実行すること
      • 何をしているのかはよくわからない
  • PropertiesFactoryBean.getObject()でPropertiesのインスタンスを返す

sample/App.java

package sample;

import java.util.Properties;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;


@SpringBootApplication
public class App
{
    private static final Logger log = LoggerFactory.getLogger(App.class);

    @Resource
    private Properties sqlProperties;

    public static void main(String[] args) {
        log.info("Hello World!");
        try(ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args)) {
            App app = ctx.getBean(App.class);
            app.run(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run(String... args) throws Exception {

        log.info(sqlProperties.getProperty("samplevalue"));

    }
}
  • DIしたいProperties型の変数に@Resourceをつける
    • @ResourceはBean名でDIされるらしい
      • 今回の場合、sqlProperties
  • getProperty()で取得

src/main/resources/sample.properties

samplevalue=hello world

実行

20:30:49.252 [main] INFO sample.App - Hello World!

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

2019-07-22 20:30:49.827  INFO 42668 --- [           main] sample.App                               : Starting App on Plus-OP021 with PID 42668 (C:\pleiades\workspace\spring-boot-properties-load\target\classes started by t-ohsaka in C:\pleiades\workspace\spring-boot-properties-load)
2019-07-22 20:30:49.828  INFO 42668 --- [           main] sample.App                               : No active profile set, falling back to default profiles: default
2019-07-22 20:30:50.507  INFO 42668 --- [           main] sample.App                               : Started App in 1.052 seconds (JVM running for 1.604)
2019-07-22 20:30:50.510  INFO 42668 --- [           main] sample.App                               : hello world!

わーできた!!簡単!!

今回のプロジェクトはここ に置いた


エラーが出たときのメモ

  • Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.util.Properties' available: expected single matching bean but found 2: sqlProperties,systemProperties
    • SpringのDIは型で一致したものをDIするため、同じ型のものがあると、どっちかわからない
    • @Resourceで変数名を@Beanをつけたメソッド名と同じにする
  • Bean named 'sqlProperties' is expected to be of type 'java.util.Properties' but was actually of type 'org.springframework.beans.factory.support.NullBean'
    • 正しく@Beanで返せていなかった
    • PropertiesFactoryBean.afterPropertiesSet()を実行する
      • SpringのDIコンテナはbeanを生成しプロパティがセットされた後にafterPropertiesSet()メソッドを呼び出します
      • 5.DIされたときの動作の制御(カスタマイズ)について - soracane
      • JavaDocの和訳
        • すべてのBeanプロパティを設定し、BeanFactoryAware、ApplicationContextAwareなどを満たした後で、格納されているBeanFactoryによって呼び出されます。

        • このメソッドを使用すると、Beanインスタンスは、すべてのBeanプロパティが設定されたときに、全体の構成の検証と最終的な初期化を実行できます。

        • んーわからん

参考文献

【Java】lombokで自動生成されるsetter(getter)を上書きする

例えば、特定のプロパティのみ、自分で書いたsetterを使いたいときとか

やることは

  • ただ単にsetXxx()を作ればいいだけ

だった

以下、サンプルコード

サンプル

People.java

以下のようなPeopleクラスを作成する

package sample;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class People {
    private String name;
    private int age;

    // @Dataで自動生成されるsetAge()を上書きする
    public void setAge(int age) {
        this.age = age + 100;
    }
}

また、lombokアノテーションは以下の通り

  • @Data: すべてのプロパティに対してsetXxx()getXxx()を生成
  • @NoArgsConstructor: 引数なしのコンストラクタを生成
  • @AllArgsConstructor: 全プロパティを引数に取るコンストラクタを生成

App.java

package sample;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
       People people = new People("Taro", 11);
       // 自分で定義したsetAge()が呼ばれる
       people.setAge(20);

       System.out.println(people);  // People(name=Taro, age=120)
    }
}

おぉ、しっかりと100足されている!

【GitHub】PullやPushでパスワードを聞かれないように設定する

~/.ssh/id_rsa(秘密鍵)と~/.ssh/id_rsa.pub(公開鍵)を作る

> ssh-keygen -t rsa

~/.ssh/id_rsa~/.ssh/id_rsa.pubが生成される

GitHubに登録する

Settings > SSH and GPG kers > SSH keys > New SSH key~/.ssh/id_rsa.pubの内容を貼り付ける

  • 接続の確認
> ssh -T git@github.com
Hi tamago324! You've successfully authenticated, but GitHub does not provide shell access.

ローカルリポジトリの設定を変更する

GitHubリポジトリClone or downloadUse SSHのテキストをコピーし、以下のコマンドを実行する

> git remote set-url origin xxxxxx

秘密鍵のパスを指定する( ~/.ssh/configの作成)

秘密鍵を以下のように生成した場合

> ssh-keygen -t rsa -f ~/.ssh/id_rsa_github

以下のような~/.ssh/configを作成する(全く同じ記述で作成する)

Host github github.com
    HostName github.com
    IdentityFile ~/.ssh/id_rsa_github
    User git

接続の確認

> ssh -T git@github.com
Hi tamago324! You've successfully authenticated, but GitHub does not provide shell access.

参考文献

【Python】typing.NamedTuple を使う

typing.NamedTuple: 型がついているcollection.namedtupleを定義できる

書き方

from typing import NamedTuple, Optional


class Table(NamedTuple):
    name: str
    alias: str

default値の設定

デフォルト値の設定されていないフィールドの後ろのみ書ける

from typing import NamedTuple


class Table(NamedTuple):
    name: str
    alias: str = 'TBL1'
  • Noneをデフォルト値で設定する場合、Optional[str] = Noneのようにする
from typing import NamedTuple, Optional


class Table(NamedTuple):
    name: str
    alias: Optional[str] = None

参考文献