简体   繁体   English

具有两个相同类型字段的JPA实体

[英]JPA Entity with two fields of the same type

I'm trying to have 2 fields of the same domain class in my entity and I'm getting this error: 我试图在我的实体中使用同一域类的2个字段,但出现此错误:

org.hibernate.MappingException: Could not determine type for: com.packt.webapp.domain.User, at table: opinions, for columns: [org.hibernate.mapping.Column(author)] org.hibernate.MappingException:无法确定以下类型:com.packt.webapp.domain.User,在表:意见,针对列:[org.hibernate.mapping.Column(author)]

My entities: 我的实体:

@Entity
@Table(name="opinions")
public class Opinion {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @NotNull
    private String text;
    @NotNull
    private String date;
    @ManyToOne
    @JoinColumn(name="commented_user")
    private User writtenTo;
    private User author;

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String username;
    private String password;
    @OneToMany(mappedBy="writtenTo")
    private List<Opinion> opinions;

I just want to map opinions to commented users and storage author of comment in author field. 我只想将评论映射到评论用户和author字段中评论的存储作者。 When I remove author field, everything works. 当我删除author字段时,一切正常。 Whats wrong with this example? 这个例子怎么了?

Try annotating also author? 尝试注释作者吗?

@ManyToOne
@JoinColumn(name="author")
private User author;

It's complaining that it doesn't know how to map the author field. 它抱怨说它不知道如何映射author字段。 You can provide a mapping similar to how you mapped writtenTo . 您可以提供类似于您映射writtenTo映射。 An opinion has one author and an author can have authored many opinions. 一个意见只有一个作者,一个作者可以发表许多意见。

If you would like to ignore a field for mapping, annotate it with @Transient . 如果您想忽略要映射的字段,请使用@Transient对其进行注释。 The transient annotation prevents that field from being persisted to the database otherwise you have to map it like so: 瞬态注释可防止将该字段持久化到数据库中,否则必须像这样映射它:

Opinion entity: 意见实体:

@Entity
@Table(name="opinions")
public class Opinion {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotNull
    private String text;

    @NotNull
    private String date;

    @ManyToOne
    @JoinColumn(name="commented_user")
    private User writtenTo;

    // map author to User entity
    @ManyToOne
    @JoinColumn(name="authored_user")
    private User author;

    // getters and setters
}

User entity: 用户实体:

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String username;

    private String password;

    @OneToMany(mappedBy="writtenTo")
    private List<Opinion> opinions;

    // map opinions to the author
    @OneToMany(mappedBy="author")
    private List<Opinion> authoredOpinions;

    // getters and setters
}

Just apply the @ManyToOne annotation at both the User fields. 只需在两个User字段上应用@ManyToOne批注。

@ManyToOne
@JoinColumn(name="commented_user")
private User writtenTo;
@ManyToOne
@JoinColumn(name="author")
private User author;

But there is a more flexible solution to problems like this. 但是,对于此类问题,存在更灵活的解决方案。 Replace the @OneToMany and @ManyToOne relations by @ManyToMany ones. 用@ManyToMany替换@OneToMany和@ManyToOne关系。 Create a User and a Role entity (with descendats for the ones with specific fields). 创建一个用户和一个角色实体(带有特定字段的后代)。 A User could have many roles (writer, author, etc) and a Role could be played by many users. 一个用户可以有许多角色(作家,作者等),而一个角色可以由许多用户扮演。 In this case you can change your mind and create/remove/attach/detach roles dynamically without any data structure changing on the existing tables. 在这种情况下,您可以改变主意并动态创建/删除/附加/分离角色,而无需更改现有表上的任何数据结构。

@Entity
public class User
{
  @Id
  private Long id;
  @Column
  private String name;
  @ManyToMany
  @JoinTable(
      name="User_Role",
      joinColumns=@JoinColumn(name="UserID", referencedColumnName="ID"),
      inverseJoinColumns=@JoinColumn(name="RoleID", referencedColumnName="ID"))
  private List<Role> roles;
}

@Entity
public class Role
{
  @Id
  private Long id;
  @Column
  private String name;
  @ManyToMany( mappedBy="roles" )
  private List<User> users;
}

And you can get/check the user roles by role ids/names using a utility class: 您可以使用实用程序类按角色ID /名称获取/检查用户角色:

puclic class RoleUtility
{
  public Role getUserRoleByName( User user_, String roleName_ )
  {
    User retRole = null;
    Iterator<Role> i = roles_.iterator();
    while ( ( retRole == null ) && i.hasNext() )
    {
      Role role = (Role) i.next();
      if ( roleName_.isEqual( role.getName ) )
        retRole = role;
    }
    return retRole;
  }
}

The client code to checking a role: 客户端代码来检查角色:

User user = ...
Role role = RoleUtility.getRoleByName( user.getRoles(), roleName );

Stay at you example with this solution you can add a censor/moderator to the opinion or something like that without any data structure changing. 在这个解决方案的例子中,您可以在不改变任何数据结构的情况下,将意见检查者/主持人添加到意见或类似内容中。

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

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