Grails有很多关系迁移

时间:2011-07-12 05:19:56

标签: grails migration many-to-many gorm

您好我有两个域类如下

class Users {

    String password
    String firstName
    String lastName
    String emailAddress
    String username
    Company company
.....
    static hasMany = [projects:Projects];
}

另一个班级

class Projects {
    String projectName
    String description
    Users projectLead
    Date dateCreated
    Date lastUpdated
    static belongsTo = Users
}

这些类显然有一对多关系,但现在我想通过添加“ProjectMembership”类将其更改为多对多关系,但我遇到的问题是我的应用程序已经投入生产并且已经有人已经使用该应用程序。在这种情况下,他们已经在db中有一个用户 - >多个项目。在这种情况下,我如何迁移现有数据并将我的prod应用程序更改为m2m关系,如下所示。

class Users {

    String password
    String firstName
    String lastName
    String emailAddress
    String username
    Company company
.....
    static hasMany = [projectMemberships:ProjectMemberships];
}

另一个班级

class Projects {
    String projectName
    String description
    Users projectLead
    Date dateCreated
    Date lastUpdated
    static hasMany = [projectMemberships:ProjectMemberships];
}

class ProjectMemberships{
    Users u
    Projects p
}

1 个答案:

答案 0 :(得分:2)

最好使用像Liquibase这样的迁移工具,http://grails.org/plugin/database-migration插件可能是Grails中最好的插件,因为它使用Liquibase并与GORM紧密集成。但这个很容易手工完成。

我不会使用hasMany,因为您可以轻松管理ProjectMemberships课程中的所有内容,因此您的UsersProjects课程将

class Users {
   String password
   String firstName
   String lastName
   String emailAddress
   String username
   Company company
.....
}

class Projects {
   String projectName
   String description
   Date dateCreated
   Date lastUpdated
}

我选择使用复合键的ProjectMemberships类,这需要它实现Serializable并且有一个好的hashCodeequals

import org.apache.commons.lang.builder.HashCodeBuilder

class ProjectMemberships implements Serializable {
   Users u
   Projects p

   boolean equals(other) {
      if (!(other instanceof ProjectMemberships)) {
         return false
      }

      other.u?.id == u?.id && other.p?.id == p?.id
   }

   int hashCode() {
      def builder = new HashCodeBuilder()
      if (u) builder.append(u.id)
      if (p) builder.append(p.id)
      builder.toHashCode()
   }

   static ProjectMemberships get(long userId, long projectId) {
      find 'from ProjectMemberships where u.id=:userId and p.id=:projectId',
         [userId: userId, projectId: projectId]
   }

   static ProjectMemberships create(Users u, Projects p, boolean flush = false) {
      new ProjectMemberships(u: u, p: p).save(flush: flush, insert: true)
   }

   static boolean remove(Users u, Projects p, boolean flush = false) {
      ProjectMemberships instance = ProjectMemberships.findByUsersAndProjects(u, p)
      if (!instance) {
         return false
      }

      instance.delete(flush: flush)
      true
   }

   static void removeAll(Users u) {
      executeUpdate 'DELETE FROM ProjectMemberships WHERE u=:u', [u: u]
   }

   static void removeAll(Projects p) {
      executeUpdate 'DELETE FROM ProjectMemberships WHERE p=:p', [p: p]
   }

   static mapping = {
      id composite: ['p', 'u']
      version false
   }
}

使用ProjectMemberships.create()添加用户与项目之间的关系,并使用ProjectMemberships.remove()将其删除。

运行grails schema-export以查看更新的DDL(它将在target/ddl.sql中)。运行project_memberships表的create table语句,例如

create table project_memberships (
   p_id bigint not null,
   u_id bigint not null,
   primary key (p_id, u_id)
)

然后使用此SQL填充它(取决于您的数据库,您可能需要稍微不同的语法):

insert into project_memberships(p_id, u_id) select id, project_lead_id from projects

最后从project_lead_id表中删除projects列。

当然,在进行任何更改之前,请先进行数据库备份。

您可以使用

获取用户的项目
def projects = ProjectMemberships.findAllByUsers(user)*.p

和类似项目的用户

def users = ProjectMemberships.findAllByProjects(project)*.u