2017-05-14 190 views
0

我需要关于bean属性的hibernate映射的帮助,指的是多个类。如何在休眠状态下动态地映射对象

在我的应用程序中,我们正在实施权限。这些权限不是特定于某个用户的,它可能基于组(包含用户列表)和角色。所以,权限将适用于用户,角色和组。

以下是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 - 使用Hibernate> dependentObject。我不知道这是否可能,请帮助我。

回答

0

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

@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) 

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

另一个附加的好处是,如果你的AppPermission有你需要的存储特定于依赖对象的类型的属性,你可以自由的属性添加到子类,这些属性在特定子类的表分开存放。

该设置还会消除您的AppObjectType表,因为该表现在作为Hibernate的鉴别器模式的一部分进行驱动。请注意,如果您有其他“对象类型”,则需要使用此设置介绍其具体实现。

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