26784


スタックオーバーフローの利用が初めてのものです。  
やり取りなどで、ぎこちない部分が多々あるかと思いますが、  
どうかよろしくお願いいたします。

仕事でPlay Framework 2.5の利用を検討しております。  
公式のドキュメントを見ながら設定を進めておりますが、  
複数DB接続の箇所で手詰まりとなっております。

コードはgithubにアップロードしております。  
<https://github.com/junichimura/play2.5_multiple_database_connection>  
(動作させるためには、事前に公式より、activator最新版をダウンロードしておく必要があります。)

もちろんgithubのファイルをダウンロードしたくない方がいらっしゃれば、Web上でコードを開示させていただきます。

また、現在発生しているエラーは以下のようなものです。

[code]

    [error] application -
    
    ! @70c4075ao - Internal server error, for (GET) [/second/set/sample] ->
    
    play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: javax.persistence.PersistenceException: The type [class models.second.SampleTable2] is not a registered entity? If you don't explicitly list the entity classes to use Ebean will search for them in the classpath. If the entity is in a Jar check the ebean.search.jars property in ebean.properties file or check ServerConfig.addJar().]]
            at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
            at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
            at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
            at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
            at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:98)
            at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
            at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
            at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
            at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
            at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
    Caused by: java.util.concurrent.CompletionException: javax.persistence.PersistenceException: The type [class models.second.SampleTable2] is not a registered entity? If you don't explicitly list the entity classes to use Ebean will search for them in the classpath. If the entity is in a Jar check the ebean.search.jars property in ebean.properties file or check ServerConfig.addJar().
            at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
            at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
            at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593)
            at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
            at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
            at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
            at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:21)
            at scala.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:18)
            at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
            at scala.concurrent.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:63)
    Caused by: javax.persistence.PersistenceException: The type [class models.second.SampleTable2] is not a registered entity? If you don't explicitly list the entity classes to use Ebean will search for them in the classpath. If the entity is in a Jar check the ebean.search.jars property in ebean.properties file or check ServerConfig.addJar().
            at com.avaje.ebeaninternal.server.persist.DefaultPersister.createRequest(DefaultPersister.java:1189)
            at com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:208)
            at com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:199)
            at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1461)
            at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1454)
            at com.avaje.ebean.Model.save(Model.java:208)
            at controllers.CheckFind.setS2(CheckFind.java:40)
            at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$4$$anonfun$apply$4.apply(Routes.scala:167)
            at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$4$$anonfun$apply$4.apply(Routes.scala:167)
            at play.core.routing.HandlerInvokerFactory$$anon$4.resultCall(HandlerInvoker.scala:157)
    
[/code]

なお、該当するSampleTable2クラスには、@Entity アノテーションを付加している状態です。

application.confでの設定は、以下の通りです。

[code]

    db {
      default.driver=com.mysql.jdbc.Driver
      default.url="jdbc:mysql://localhost/skysea?characterEncoding=UTF-8"
      default.username=skysea
      default.password="skysea"
    
      second.driver=com.mysql.jdbc.Driver
      second.url="jdbc:mysql://localhost/skysea2?characterEncoding=UTF-8"
      second.username=skysea
      second.password="skysea"
    
      # You can turn on SQL logging for any datasource
      # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements
      #default.logSql=true
    }
    
    ebean {
      default = ["models.first.*"]
      second = ["models.second.*"]
    }
    
[/code]

知見をお持ちの方がいらっしゃいましたら、お力を貸していただければ幸いです。  
どうかよろしくお願いいたします。


CC BY-SA 3.0
2016-06-10T07:20:14.043
26614
2016-06-16T08:36:16.287
2016-06-10T08:11:31.200
16809
16809
question
java playframework
Play Framework 2.5 で複数DB接続


解決いたしました。

結論から申し上げますと、Play FrameworkとEbeanのドキュメントには特に役立つ記載はありませんでした。  
日本語のドキュメントが全くないため、とても苦戦しました。  
同様のことでお困りの方が今後いらっしゃるかもしれませんので、  
解決方法を簡単にご紹介しておきます。  
（詳しい内容は、質問本文中のgithubへのリンクからソースコードをご覧ください。）

解決方法としては、application.confに接続先DB情報を記載します。

**application.conf**

[code]

    db {
      first.driver=com.mysql.jdbc.Driver
      first.url="jdbc:mysql://192.168.0.155/skysea?characterEncoding=UTF-8"
      first.username=skysea
      first.password="skysea"
    
      second.driver=com.mysql.jdbc.Driver
      second.url="jdbc:mysql://192.168.0.155/skysea2?characterEncoding=UTF-8"
      second.username=skysea
      second.password="skysea"
    
    }
    
    ebean {
      first = ["models.first.*"]
      second = ["models.second.*"]
    }
    
    play.ebean.defaultDatasource = "ebean.first"
    
[/code]

com.avaje.ebean.Modelを継承するabstructクラスを作成します。  
この際、接続先のDB情報をdbメソッドで定義します。  
例)

[code]

    package models.first;
    
    import javax.persistence.MappedSuperclass;
    
    import com.avaje.ebean.Ebean;
    import com.avaje.ebean.EbeanServer;
    import com.avaje.ebean.bean.EntityBean;
    
    @MappedSuperclass
    public abstract class Model extends com.avaje.ebean.Model {
    
        // application.conf に記載のサーバを指定する。
        public static final String server = "second";
    
        public static EbeanServer db() {
            return Ebean.getServer(server);
        }
    
        public void markAsDirty() {
            db().markAsDirty(this);
        }
    
        public void markPropertyUnset(String propertyName) {
            ((EntityBean) this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
        }
    
        public void save() {
            db().save(this);
        }
    
        public void update() {
            db().update(this);
        }
    
        public void insert() {
            db().insert(this);
        }
    
        public boolean delete() {
            return db().delete(this);
        }
    
        public void update(String server) {
            db(server).update(this);
        }
    
        public void insert(String server) {
            db(server).insert(this);
        }
    
        public boolean delete(String server) {
            return db(server).delete(this);
        }
    
        public void refresh() {
            db().refresh(this);
        }
    
    }
    
[/code]

モデルを作成する際、保存先のDBを設定しているcom.avaje.ebean.Modelの継承クラスをスパークラスとしてextendsします。

[code]

    package models.first;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    
    @Entity
    public class SampleTable1 extends Model {
    
        @Id
        public Integer sampleTable1Id;
    
        public String sampleTable1Value;
    
        public static Find<Integer, SampleTable1> find = new Find<Integer, SampleTable1>(Model.server, SampleTable1.class){};
    
    }
    
[/code]

あとは使うだけです。

[code]

    package controllers;
    
    import java.util.List;
    
    import models.first.SampleTable1;
    import models.second.SampleTable2;
    import play.mvc.Controller;
    import play.mvc.Result;
    
    public class CheckFind extends Controller {
    
        public Result setS1(String str){
    
            SampleTable1 s = new SampleTable1();
            s.sampleTable1Value = str;
            s.save();
    
            return getS1(String.format("[Info] (%s) save success.\n\n", str));
        }
    
        public Result getS1(String message){
            List<SampleTable1> sList = SampleTable1.find.where().findList();
    
            StringBuffer sb = new StringBuffer(message);
            if(sList.size() == 0){
                sb.append("table is empty...");
            }
    
            for(SampleTable1 s : sList){
                sb.append(String.format("id: %3d (%s)\n", s.sampleTable1Id, s.sampleTable1Value));
            }
    
            return ok(sb.toString());
        }
    
        public Result updateS1(int id, String updStr){
            SampleTable1 s = SampleTable1.find.byId(id);
    
            String before = s.sampleTable1Value;
            s.sampleTable1Value = updStr;
            s.save();
    
            return getS1(String.format("[Info] (id: %s) %s -> %s\n", s.sampleTable1Id, before, s.sampleTable1Value));
        }
    
    }
    
[/code]

以上です。


CC BY-SA 3.0
2016-06-16T08:36:16.287
26784
2016-06-16T08:36:16.287
16809
26614
answer