Play framework의 Database는 Evolutions scripts 에 의해서 startup/shutdown에 액션을 취할수 있다. plain SQL로 작성되고 conf/evolutions/{database name} 위치에 있다. 1.sql이 실행되고 2.sql이 있으면 수행되는 형식이다.

막 이전에 yaml 파일과 GlobalSetting를 상속받아서 테스트 데이터를 입력하였는데 거기에 scripts로 추가적으로 테스트 데이터를 입력해보도록 하자.


현재 포스팅을 하고 있는 대상 tutorial 웹어플리케이션의 default database name은 [default] 이다.

application.conf

# Database configuration

# ~~~~~ 

# You can declare as many datasources as you want.

# By convention, the default datasource is named `default`

#

db.default.driver=org.h2.Driver

db.default.url="jdbc:h2:mem:play"




현재 우리 프로젝트의 폴더 모습은 위와 같다. 자동으로 생성된 폴더와 1.sql도 보일것이다. 이런거 만든적이 없다고 거짓말 하지 마라. 바로 이전 포스팅에서 Apply this script now! 를 눌렀잖아?

저기에 2.sql을 만들어 보자. (2개의 테스트 데이터를 넣는 sql문이다)

# Sample data 대충 요롷게

# --- !Ups

insert into message (id, content)  values  (5, 'test message'), (6, 'last message');

# --- !Downs





위의 모습처럼 [허용해줘!버튼]을 볼 수 있다. 이러한 스크립트는 데이터를 넣을때도 유용할 수 있지만, 협업하는 개발자가 같은 테이블임에도 DB스키마다 다르게 작업하는등의 이슈가 있을때 사용할 수 있겠지?


여기서 궁금한게 있지 않나? 1.sql 다음에 10.sql을 쓰면 과연 수행이 될것인가? 2.sql을 10.sql로 변경하고 Play Command Line에서 reboot를 입력한후 run하였다. 하지만 10.sql은 수행되지 않는다.

첫DB는 default 이르을 가져야 하고, 1.sql 뒤에 2.sql 의 순서대로 script는 실행된다. (라고 난 확인했다~)

Evolutions scripts를 수행하는 native code를 분석하면 좀 더 명확하게 알수 있겠지만, 난 지금 play framework의 사용법을 배우는 중이라서 그건 니네들이 알아서 보자.-_-z



신고


간단한 화면도 DB를 이용한 CRUD 중 'C'를 학습해 보도록 하겠다 Play Framework는 기본적으로 H2를 임베딩하고 있기때문에 주석을 단3줄만 제거하는것으로 설정을 끝낼수 있다.


1. application.conf 의 수정

# Database configuration
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
# Ebean configuration ebean.default="models.*"

한줄 한줄 설명하기 보단 따라하다보면 언젠가는 이해할 수 있을 것이다.

기본 DB명을 [message] 로 정하고 위의 3줄을 입력하였다. (기존 주석 처리된 라인을 이용해도 된다)

default DB가 없이는 다른 Database name을 지정할 수 없다. 즉 첫 번째는 무조건 default이다. 아... 삽질이여 ㅠ_ㅠ

db.default.url="jdbc:h2:mem:play" 는 H2 디비 메모리 모드, 만약 파일로 설정할경우는 

db.default.url="jdbc:h2:path_db_name.db" 처럼 사용하자

* 참고#1 : http://www.h2database.com/html/cheatSheet.html



2. .Model 생성

기본 프로젝트에서는 Models 패키지가 없으므로 app.models 패키지를 추가한다. 그리고 Message.java를 입력한다.

package models;
 
import java.util.List;
import javax.persistence.*;
import play.data.validation.Constraints.Required;
import play.db.ebean.Model;
 
@Entity
public class Message extends Model {
 
    @Id Long id;
    @Required String content;
     
    static Finder<Long, Message> find = new Finder(Long.class, Message.class);
     
    public Message(String content){
        this.content = content;
    }
     
    public static List<Message> all(){
        return find.all();
    }
     
    public static Message findById(Long id){
        return find.ref(id);
    }
 
}

3. Routes 수정

GET     /  는 필요없다고 삭제하는 그런 사소한 얘가 아니다. 얘는 나두고 한 줄 더 추가하자.

# Home page
GET     /	controllers.Application.index()
GET 	/list	controllers.Application.getList()



4. Application.java의 수정

index()는 /list으로 리다이렉트 하도록 수정하고, /list에 매핑되는 Entry Point Method를 하나 작성하자.

package controllers;

import java.util.List;

import models.Message;
import play.mvc.Controller;
import play.mvc.Result;

public class Application extends Controller {
  
  public static Result index() {
    return redirect(routes.Application.getList());
  }
  
  public static Result getList(){
	  List messages = Message.all();
	  return TODO;
  }
  
}


5. 중간 실행 단계

위의 코드를 정상적으로 작성하고 http://localhost:9000를 호출하면 아래와 같은 화면을 볼 수 있을 것이다. 

붉은 화면이라고 해서 노여워하거 슬퍼하지 말고 Apply this script now! 버튼을 누른다. models의 해당 Model Object를 기반으로 DDL을 생성해 준다. 이후 return TODO로 작성을 하였기 때문에 TODO의 화면을 볼 것이다. 그리고 콘솔에서는 database [default]가 운영중인 메세지를 노출한다

[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Application started (Dev)


6. 간단한 View 파일의 생성

Application.java 의  getList() 를 수정해보자

  public static Result getList(){
	  List messages = Message.all();
	  return ok(views.html.message.list.render(messages) );
  }


다음 app/views/message 폴더에 list.scala.html 파일을 생성한다

@(messages: List[Message])
[html]
	[head][/head]
	
	[body]
		[h1]@if( messages.size() == 0) { 
			No Message 
		} else { 
			@messages.size() POST(s) 
		}[/h1]
	[/body]
[/html]


먼가 Message 데이터가 없기 때문에 Size = 0 일꺼고, No Message 를 화면에 출력한다는것을 어렴풋이 생각할 수 있다.

message 폴더에 list.scala.html 이기 때문에 Action Method에서는 message.list.render(값) 으로 사용한다. 그리고 Action Method에서 넘어오는 인자들은 view page의 1라인에서 각 변수에 할당하여 사용하고 있다.

데이터가 없으니 이거 뭐 확인 할 길이 있나...? 더미 데이터를 한번 넣어보자.


application.conf 를 보면 아래 부분을 볼 수 있다.

# Global object class
# ~~~~~
# Define the Global object class for this application.
# Default to Global in the root package.
# global=Global
root package (app) 에 Global 이름으로 생성할 수도 있지만, 간지를 위해 #global=Global 을 global=InitSampleData 으로 수정하고 /app/InitSampleData.java 파일을 작성하자
import java.util.List;
import java.util.Map;

import models.Message;
import play.Application;
import play.GlobalSettings;
import play.libs.Yaml;
import com.avaje.ebean.Ebean;

public class InitSampleData extends GlobalSettings {
	@Override
	public void onStart(Application app) {
		Map> samples = (Map>)Yaml.load("sample.yml");
		Ebean.save(samples.get("message"));
	}
	
}
다음 conf/sample.yml 파일에 샘플 데이터를 입력한다
message:

    - !!models.Message
        id:     11
        content:  content from sample.yml #1

    - !!models.Message
        id:     12
        content:  content from sample.yml #1


데이터 형식은 Yaml로 작성해야 하고, play.libs.Yaml.load(String fileName) 으로 로딩할 수 있다. 그리고 GlobalSettings 를 상속 받으면 application start-up / shut-down 에  작업을 할 수 있다.

(물론 application start-up될때마다 수행되므로, shut-down할때 삭제하던지 하는 방법등으로 중복 insert를 방지하는건 기본센스)

이제 실행해보면, 기본적으로 2개의 데이터가 있다는 결과 화면을 볼 수 있다~!


테스트 데이터를 넣는 방법은  Evolutions scripts 으로도 가능한데, 이건 다른 포스팅에서 작성한다. 


추가.

SBT에서 [package-src]로 추출한 소스를 첨부한다. 받아서 jar를 푼다음, eclipsify 를 이용한다면 쉽게 볼 수 있을것이다. 


tutorial_2.9.1-1.0-SNAPSHOT-sources.jar




신고


티스토리 툴바