9月9日

ACID特性

Atomicity・Consistency・Isolation・Durabilityを考慮してプログラミングしよう。

入力フィールドのチェックを username と password で分割する。(Atomicity)

$(function() {
	$('[type=submit]').attr('disabled', true);
	$('[name=username]').on('keyup', function() {
		checkUserNameField();
	});
	$('[type=password]').on('keyup', function() {
		checkPasswordField();
	});
});

function checkUserNameField() {
	var name = $('[name=username]').val();
	if (name.length == 0) {
		$('[type=submit]').attr('disabled', true);
		$('div.err').text('ユーザー名を入力してください。');
		return;
	}
	$('div.err').text('');
	$('[type=submit]').attr('disabled', false);
}

function checkPasswordField() {
	var p1 = $('[name=password]').val();
	var p2 = $('[name=password2]').val();
	if (p1 != p2) {
		$('div.err').text('パスワードが一致していません。');
		$('[type=submit]').attr('disabled', true);
		return;
	}
	$('div.err').text('');
	$('[type=submit]').attr('disabled', false);
}

ログインしたユーザー名を表示する

マイページでは、ログインしたユーザー名を表示してみよう。
メソッドに Principal 引数を追加すると、ログインしたユーザーに関する情報をもらえる。

MyController.java

	@RequestMapping(value = "/mypage")
	public ModelAndView top(ModelAndView mav, Principal p) {
		mav.setViewName("mypage");
		mav.addObject("username", p.getName());
		return mav;
	}

HTMLテンプレートで受け取った username を表示する。

mypage.html

<body>
    <h1>マイページ</h1>
    <p>ようこそ、<span th:text="${username}"></span>さん!</p>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="ログアウト" />
    </form>
</body>

ユーザーの情報を持たせるために Profile クラスを作成する。

Profile.java

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column
    @NotNull
    private long id;

    @Column(length = 200, nullable = false)
    @NotEmpty
    private String username;

    @Column
    private String profile;

	public long getId() {
		return id;
	}

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

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getProfile() {
		return profile;
	}

	public void setProfile(String profile) {
		this.profile = profile;
	}

}

エンティティを作ったので対応するリポジトリを作成する。

ProfileRepository.java

package jp.abc;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProfileRepository extends JpaRepository<Profile, Long> {

}

Principal からは username しか取得できないので、 username をもとに Profile を取得するメソッドをリポジトリに追加する。

package jp.abc;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProfileRepository extends JpaRepository<Profile, Long> {
	public Optional<Profile> findByUsername(String username);
}

コントローラで、Profileを検索してみて、なかったら新規登録する。

	@RequestMapping(value = "/mypage")
	public ModelAndView top(ModelAndView mav, Principal p) {
		mav.setViewName("mypage");
		mav.addObject("username", p.getName());
		Optional<Profile> data = repository.findByUsername(p.getName());
		Profile profile = data.get();
		if (profile == null) {
			profile = new Profile();
			profile.setUsername(p.getName());
			repository.saveAndFlush(profile);
		}
		mav.addObject("profile", profile);
		return mav;
	}

HTMLテンプレートでは、profile の情報も表示してみる。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>login</title>
</head>
<body>
    <h1>マイページ</h1>
    <p>ようこそ、<span th:text="${username}"></span>さん!</p>
    <p th:text="${profile.username}"></p>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="ログアウト" />
    </form>
</body>
</html>

コントローラのコードが悪かったようで、例外が発生した。

java.util.NoSuchElementException: No value present
	at java.util.Optional.get(Optional.java:135) ~[na:1.8.0_152]
	at jp.abc.MyController.top(MyController.java:59) ~[classes/:na]

値が存在しないときは Optional#get() を呼んではいけないらしいので、コードを書き換える。

	@RequestMapping(value = "/mypage")
	public ModelAndView top(ModelAndView mav, Principal p) {
		mav.setViewName("mypage");
		mav.addObject("username", p.getName());
		Optional<Profile> data = repository.findByUsername(p.getName());
		Profile profile;
		if (!data.isPresent()) {
			profile = new Profile();
			profile.setUsername(p.getName());
			repository.saveAndFlush(profile);
		} else {
			profile = data.get();
		}
		mav.addObject("profile", profile);
		return mav;
	}

Tweet クラスを作成する。

Tweet.java

package jp.abc;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Tweet {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column
    @NotNull
    private long id;

    @Column(length = 200, nullable = false)
    @NotEmpty
    private String content;

    @Column(nullable = false)
    private Date time;

    @ManyToOne
    private Profile profile;

	public long getId() {
		return id;
	}

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

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Date getTime() {
		return time;
	}

	public void setTime(Date time) {
		this.time = time;
	}

	public Profile getProfile() {
		return profile;
	}

	public void setProfile(Profile profile) {
		this.profile = profile;
	}
}

Profile と Tweet を連携する。

Profile.java

package jp.abc;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column
    @NotNull
    private long id;

    @Column(length = 200, nullable = false)
    @NotEmpty
    private String username;

    @Column
    private String profile;

    @OneToMany
    private List<Tweet> tweets;

	public long getId() {
		return id;
	}

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

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getProfile() {
		return profile;
	}

	public void setProfile(String profile) {
		this.profile = profile;
	}

	public List<Tweet> getTweets() {
		return tweets;
	}

	public void setTweets(List<Tweet> tweets) {
		this.tweets = tweets;
	}

}

HTMLテンプレートに投稿用フォームを追加する。

mypage.html

<body>
    <h1>マイページ</h1>
    <p>ようこそ、<span th:text="${username}"></span>さん!</p>
    <p th:text="${profile.username}"></p>
    <form th:action="@{/tweet}" th:object="${tweet}">
    	<textarea name="content" cols="40" rows="10"></textarea>
    	<br />
    	<input type="submit" value="ツイートする" />
    </form>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="ログアウト" />
    </form>
</body>

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください