LoginSignup
4
4

More than 5 years have passed since last update.

MongoDB GORM - Inheritance mapping Tips

Last updated at Posted at 2014-04-13

Hibernate/JPA 利用者にはおなじみの概念を、MongoDB GORM で実現するための Tips 。

参考

Java Persistence/Inheritance

Mapped Superclass の実現

利用シーン

  • 具象エンティティのデータのみを作成する
  • 抽象クラスは、DB上でも抽象的位置づけである(データを持たない)

Example

grails-app/domain/AbstractUser.groovy
abstract class AbstractUser {

    static mapWith = "mongo"
    static mapping = {
        name index: true
    }
    static constraints = {
        desc nullable: true
    }

    String name
    String desc

    def beforeInsert() {
        doSomething()
    }

    def afterLoad() {
        doSomething()
    }

}
grails-app/domain/User.groovy
class User extends AbstractUser {

    static mapWith = "mongo"
    static mapping = {
        order index: true
    }
    static constraints = {
        lastLoginDate nullable: true
    }

    int order
    Date lastLoginDate

}

特徴

  • indexの継承: OK
    ただし、ensureIndexが実行されるのでabstractUserコレクションは作成されてしまう
    AbstractUserに mapWith = "none" を記述するとコレクション作成を抑制できるが、mapWith = "mongo" 指定している User も強制的に除外されるので利用できない
  • constraintsの継承: OK
  • beforeInsertの継承: OK
  • afterLoadの継承: OK

注意事項

  • どちらも grails-app/domain 下に置く
    src/groovy 下では動作しない
  • バージョンによっては以下の事象に注意。
    Update is not working when properties of concrete class changed
    • 具象エンティティのプロパティのみが変更された場合に、エンティティが dirty 状態に遷移しない。
      (抽象エンティティのプロパティが変更された場合は遷移する)

Polymorphic associations

利用シーン

  • User.list()ActiveUser.count() のように、エンティティごとにクエリを発行したい場合

Example

grails-app/domain/User.groovy
class User {
    static mapWith = "mongo"
}
grails-app/domain/ActiveUser.groovy
class ActiveUser extends User {
}
grails-app/domain/InactiveUser.groovy
class InactiveUser extends User {
}

特徴

  • ドキュメントプロパティに以下のような型情報が追加される
"_class": "ActiveUser",

注意事項

  • どちらも grails-app/domain 下に置く
    src/groovy 下では動作しない
  • 親エンティティ(上の例では User)が abstract だと期待する動作をしない (save時に _class プロパティが入らない、またロードも正常に行えない)

collection per class hierarchy

利用シーン

  • Hibernate/JPA の「table per class hierarchy」的な。

Example

grails-app/domain/User.groovy
class User {
    static mapWith = "mongo"
    static mapping = {
        collection "user"
    }
}
grails-app/domain/ActiveUser.groovy
class ActiveUser extends User {
    static mapping = {
        collection "activeUser"     // 無視される
    }
}
grails-app/domain/InactiveUser.groovy
class InactiveUser extends User {
    static mapping = {
        collection "inactiveUser"   // 無視される
    }
}

特徴

  • ドキュメントプロパティに以下のような型情報が追加される
"_class": "ActiveUser",
  • 子クラスの collection 指定は無視され、全て user コレクションに保存される

注意事項

  • どちらも grails-app/domain 下に置く
    src/groovy 下では動作しない
  • 親エンティティ(上の例では User)が abstract だと期待する動作をしない (save時に _class プロパティが入らない、またロードも正常に行えない)
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4