简体   繁体   English

JPA映射-关系中的复合键

[英]JPA Mapping - Composite Key in Relationship

I have a problem with JPA mapping for a particular relation. 我对特定关系的JPA映射有问题。 In my MySQL database I have 3 entity in relationship: 在我的MySQL数据库中,我有3个关联的实体:

USER
USER_SERIAL_NUMBER VARCHAR(20) not null,
..... VARCHAR(4) not null,
..... VARCHAR(3) not null,
..... VARCHAR(10) not null,
primary key (USER_SERIAL_NUMBER)
);
OFFICE (
OFFICE_SERIAL_NUMBER VARCHAR(20) not null,
TOWN VARCHAR(15) not null,
YEAR VARCHAR(4) not null,
DESCRIPTION VARCHAR(200) not null,
NOTE VARCHAR(100) not null,
CREATION_DATE DATE not null,
LAST_UPDATE_DATE DATE not null,
primary key (OFFICE_SERIAL_NUMBER)
);

ROLE_TYPE (
ROLE_ID BIGINT not null,
DESCRIPTION VARCHAR(20) not null,
CREATION_DATE DATE not null,
LAST_UPDATE_DATE DATE not null,
primary key (ROLE_ID)
);

and the relation table 和关系表

ROLE (
ROLE_ID BIGINT not null,
USER_SERIAL_NUMBER VARCHAR(20) not null,
OFFICE_SERIAL_NUMBER VARCHAR(20) not null,
YEAR VARCHAR(4) not null,
CREATION_DATE DATE not null,
LAST_UPDATE_DATE DATE not null,
primary key (ROLE_ID, USER_SERIAL_NUMBER, OFFICE_SERIAL_NUMBER, YEAR)
);

In the relation table I have a composite key with the 3 foreign key and a local key (the year), because a user can have more (different) role on particular office in a specified year but probably will change the next year (I have to mantain the historic role). 在关系表中,我有一个包含3个外键和一个本地键(年份)的复合键,因为用户可以在指定年份在特定办公室扮演更多(不同)角色,但可能会在下一年更改(我有保持历史性作用)。

I have made many attempts to map these tables in entities but I didn't yet found the right mix so that everything works. 我做了很多尝试在实体中映射这些表,但是我还没有找到合适的组合,以便一切正常。

I would like to navigate the relationship in both direction, so I need to know who and how many are users who have a particular role in a particular office, but I also need to know in how many offices work a particular user, and what role he has. 我想双向导航关系,因此我需要知道在特定办公室中扮演特定角色的用户是谁,以及多少用户,但是我还需要知道在特定用户中有多少办公室工作?他有。

Here is the Java code: 这是Java代码:

@Entity
@Scope(ScopeType.CONVERSATION)
@Name("role")
@Table(name = "ROLE")
@IdClass(RolePK.class)
public class Role implements Serializable {

private static final long serialVersionUID = 111111111L;

@Id
@OneToOne
@Column(name="USER_SERIAL_NUMBER")
private User User;

@Id
@OneToOne
@Column(name="OFFICE_SERIAL_NUMBER")
private Office office;

@Id
@OneToOne
@Column(name="ROLE_ID")
private RoleType roleType;

@Id
@Column(name = "YEAR", length = 4, nullable = false)
private String year;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATION_DATE", nullable = false)
private Date creationDate;

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "LAST_UPDATE_DATE", nullable = false)
private Date lastUpdateDate;

… getter and setter … 
… equals and hash code …
… toString …
}

@Name("rolePK")
public class RolePK implements Serializable {

private static final long serialVersionUID = 2222222222222L;

private String office;
private Long roleType;
private String User;
private String year;

public RolePK() {

… getter and setter … 
… equals and hash code …
… toString …
}
@Entity
@Scope(ScopeType.CONVERSATION)
@Name("user")
@Table(name = "USER")
public class User implements Serializable {

private static final long serialVersionUID = 333333333333L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "USER_SERIAL_NUMBER", length = 20, nullable = false)
private String serialNumber;

… other properties… 

@OneToMany(mappedBy="user")
private Collection<Role> roleCollection;

… getter and setter … 
… equals and hash code …
… toString …


@Entity
@Scope(ScopeType.CONVERSATION)
@Name("office")
@Table(name = "OFFICE")
public class Office implements Serializable {

private static final long serialVersionUID = 55555555555555555L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="OFFICE_SERIAL_NUMBER", length=20, nullable=false)
private String officeSerialNumber;
… other properties… 

@OneToMany(mappedBy="office")
private Collection<Role> roleCollection;

… getter and setter … 
… equals and hash code …
… toString …

@Entity
@Scope(ScopeType.CONVERSATION)
@Name("roleType")
@Table(name = "ROLE_TYPE")
public class RoleType implements Serializable {

private static final long serialVersionUID = 44444444444444444L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ROLE_TYPE_ID", nullable = false)
private Long id; 
… other properties… 

@OneToMany(mappedBy="roleType")
private Collection<Role> roleCollection;

… getter and setter … 
… equals and hash code …
… toString …

I tried to implement this solution (which I had already tried before), but I still have configuration problems. 我尝试实现此解决方案(之前已经尝试过),但是仍然存在配置问题。 In this particular configuration, the error I have is that when Hibernate tries to create a query, does not seem to be able to generate a proper query. 在这种特定配置中,我的错误是,当Hibernate尝试创建查询时,似乎无法生成正确的查询。 In particular, I have the names of the properties that are not equal to the names of the columns of the relationship table. 特别是,我具有的属性名称与关系表的列名称不同。 I tried to use annotations to specify the name of the column on which to bind the property, but the query is generated using the property name and not the name of the column. 我尝试使用批注指定要在其上绑定属性的列的名称,但是查询是使用属性名而不是列名生成的。 Thus, the system throws an exception, specifically: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'roleco0_.user'in 'field list'. 因此,系统将引发异常,特别是:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:“字段列表”中的未知列“ roleco0_.user”。

Someone can help me? 有人可以帮我吗? Thanks in advance 提前致谢

Why don't you introduce an autogenerated ID in the Role table, and a unique constraint on the tuple (roleId, use, office, year). 为什么不在Role表中引入自动生成的ID,以及对元组的唯一约束(roleId,用途,办公室,年份)。 This would make sthings much much simpler. 这将使事情变得简单得多。

If you really want to continue with this composite primary key, then you should read http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id , which ends with an example of an embedded ID containing an association. 如果您确实想继续使用此复合主键,则应阅读http://docs.jboss.org/hibernate/core/3.6/reference/zh-CN/html_single/#mapping-declaration-id ,其结尾为包含关联的嵌入式ID的示例。 But be careful with your associations : they should be ManyToOne, and not OneToOne, since a user (for example) can be referenced by several roles. 但是要小心关联:它们应该是ManyToOne,而不是OneToOne,因为一个角色(例如)可以由多个角色引用用户。

You should thus have 因此,您应该拥有

@Embeddable
public class RoleId {
    @ManyToOne
    private User user;

    @ManyToOne
    private Office office;

    @ManyToOne
    private RoleType roleType;

    private int year;

    // constructor, getters, equals, hashCode
}

@Entity
public class Role {
    @EmbeddedId
    private RoleId id;

    private Date creationDate;
    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM