如何在hibernate中动态映射对象

时间:2017-05-14 13:39:01

标签: java hibernate orm

我需要有关hibernate映射的帮助,bean属性引用多个类。

在我的应用程序中,我们正在实现权限。这些权限并非特定于某些用户,它可能基于组(包含用户列表)和角色。因此,权限将适用于用户,角色和组。

以下是ddl和实体类。请检讨并帮助我。

DDL:

--stores the application users
CREATE TABLE users (
    id serial PRIMARY KEY,
    name text,
    CONSTRAINT uk_users_name UNIQUE (name)
);

--stores the application groups
CREATE TABLE groups (
    id serial PRIMARY KEY,
    name text,
    CONSTRAINT uk_groups_name UNIQUE (name)
);

--stores the application roles
CREATE TABLE roles (
    id serial PRIMARY KEY,
    name text,
    CONSTRAINT uk_roles_name UNIQUE (name)
);

--stores the application object types
CREATE TABLE app_object_types (
    id serial PRIMARY KEY,
    name text,
    CONSTRAINT uk_app_object_types_name UNIQUE (name)
);

INSERT INTO app_object_types (name) VALUES ('USERS');
INSERT INTO app_object_types (name) VALUES ('GROUPS');
INSERT INTO app_object_types (name) VALUES ('ROLES');


CREATE TABLE app_permissions (
    id serial PRIMARY KEY,
    object_type_id integer REFERENCES app_object_types(id),  -- To represent the object type 
    object_id integer, -- Objecct_id refers users -> id, groups -> id, roles - id
    permission_name text,
    CONSTRAINT uk_permissions UNIQUE (object_type_id, object_id, permission_name)
);

实体类:

@Entity
@Table(name = "users")
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private int name;

    public int getId() {
        return id;
    }

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

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }
}

@Entity
@Table(name = "groups")
public class Groups {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private int name;

    public int getId() {
        return id;
    }

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

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }
}

@Entity
@Table(name = "roles")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private int name;

    public int getId() {
        return id;
    }

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

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }
}

@Entity
@Table(name = "app_object_types")
public class AppObjectTypes {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private int name;

    public int getId() {
        return id;
    }

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

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }

}

@Entity
@Table(name = "app_permissions")
public class AppPermissions {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne
    private String permissionName;

    @ManyToOne
    private AppObjectTypes appObjectTypes;

    private int objectId;

    private Class<?> dependentObject;

    public int getId() {
        return id;
    }

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

    public String getPermissionName() {
        return permissionName;
    }

    public void setPermissionName(String permissionName) {
        this.permissionName = permissionName;
    }

    public AppObjectTypes getAppObjectTypes() {
        return appObjectTypes;
    }

    public void setAppObjectTypes(AppObjectTypes appObjectTypes) {
        this.appObjectTypes = appObjectTypes;
    }

    public int getObjectId() {
        return objectId;
    }

    public void setObjectId(int objectId) {
        this.objectId = objectId;
    }

    public Class<?> getDependentObject() {
        return dependentObject;
    }

    public void setDependentObject(Class<?> dependentObject) {
        this.dependentObject = dependentObject;
    }
}

我想将用户(或)组(或)角色bean对象映射到AppPermissions - &gt; dependentObject使用hibernate。我不知道是否有可能请帮助我。

1 个答案:

答案 0 :(得分:0)

我建议您考虑在@Inheritance实体上使用AppPermission,以便根据依赖对象类型对每个子类进行专门化。

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "OBJECT_TYPE")
public class AppPermission {
  @Id
  @GeneratedValue 
  private Long permissionId;
  private String name;
  @Column(name = "OBJECT_TYPE", insertable = false, updatable = false)
  private String objectType;
}

@Entity
@DiscriminatorValue("USER")
public class UserAppPermission extends AppPermission {
  @ManyToOne(optional = false)
  private User user;
}

@Entity
@DiscriminatorValue("ROLE")
public class RoleAppPermission extends AppPermission {
  @ManyToOne(optional = false)
  private Role role;
}

@Entity
@DiscriminatorValue("GROUP")
public class GroupAppPermission extends AppPermission {
  @ManyToOne(optional = false)
  private Group group;
}

这与您的映射的第一个区别是,您的AppPermission表的构造将与您当前的架构不同,并且看起来如下(注4个表):

Table: AppPermission
  id NOT NULL IDENTITY(1,1)
  name VARCHAR(255)
  OBJECT_TYPE VARCHAR(31)

Table: UserAppPermission
  id NOT NULL BIGINT (FK -> AppPermission)
  user_id NOT NULL BIGINT (FK -> User)

Table: RoleAppPermission
  id NOT NULL BIGINT (FK -> AppPermission)
  role_id NOT NULL BIGINT (FK -> Role)

Table: GroupAppPermission
  id NOT NULL BIGINT (FK -> AppPermission)
  group_id NOT NULL BIGINT (FK -> Group)

数据库的重点是帮助我们保持参照完整性。这就是为什么当表依赖于另一个表中的行时,应首先删除与要删除的行相关的依赖表行,以避免违反约束。这正是我将关系拆分为单独表格的原因,在这里我将每个关系定义为“optional = false”,这样它基本上代表了一个连接表。

另一个好处是,如果您的AppPermission具有您需要存储特定于依赖对象类型的属性,您可以自由地将这些属性添加到子类中,并且这些属性将分别存储在该特定子类的表中。

此设置还会删除您的AppObjectType表,因为它现在是Hibernate的鉴别器模式的一部分。请注意,如果您有其他“对象类型”,则需要使用此设置介绍其特定实现。

最后,我将OBJECT_TYPE作为不可插入和不可更新的字段暴露(您不必),因为Hibernate会为您管理。但我已经公开了它,允许你进行多态查询并确定结果对象的对象类型,而不必执行instanceof检查。