1

我看到很多关于主题的教程和文章,但我无法理解一件事。例如:我有“用户”表,其中包含字段“id”、“名称”,并且我有“UserBanned”表,其中包含字段“userid”和“reason”。UserBanned.userid - 它是 User.id 字段上的链接(外键)。

因此,hiberante 中的模型如下所示:

@Entity
@Table(name = "user")
@DynamicInsert
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "user_id_generator")
    @SequenceGenerator(name = "user_id_generator", sequenceName = "user_id_seq")
    protected Integer id;

    @Column
    protected Integer name;

    @OneToOne (mappedBy = "user", cascade = CascadeType.ALL)
    protected UserBanned userBanned;

和 UserBanned 模型:

@Entity
@Table(name = "userbanned")
@DynamicInsert
public class UserBanned{

    @Id
    @Column(name="userid", unique=true, nullable=false)
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="user"))
    protected Integer userid;

    @Column
    protected String reason;

    @OneToOne
    @PrimaryKeyJoinColumn
    protected User user;

它有效。我可以使用以下代码创建新用户和禁止用户:

    User user = new User();
    user.setName(name);
    UserBanned userBanned = new UserBanned ();
    userBanned.setReason(reason);

    user.setUserBanned(userBanned );
    userBanned.setUser(user);

    clientService.store(user);

但是,当我尝试执行 gson.toJson(client) 时,我得到了 stackoverflow 错误 - 因为 Gson 无法处理序列化数据中的循环引用。但是我的头脑无法理解为什么我必须在 UserBanned 中设置用户?!为什么我不能只拥有模型用户?

我的问题:我如何在休眠中组织这样的关系(与外键一对一),比如用户(不仅有 UserBanned,而且还有 UserVIP 等实体)?

4

2 回答 2

2

您应该从序列化和反序列化中排除循环引用(User::userBanned或)之一。您可以在gson-documentation 中了解它。UserBanned::userGson

添加一些注释

  @Retention(RetentionPolicy.RUNTIME)
  @Target({ElementType.FIELD})
  public @interface Exlude 
  {
  }

创建排除策略

public class MyExclusionStrategy implements ExclusionStrategy 
{
    public boolean shouldSkipClass(Class<?> clazz) 
    {
      return false;
    }

    public boolean shouldSkipField(FieldAttributes f) 
    {
      return f.getAnnotation(Exlude.class) != null;
    }
}  

创建Gson实例GsonBuilder

Gson gson = new GsonBuilder()
        .setExclusionStrategies(new MyExclusionStrategy())
        .create();  

UserBanned::user用注解@Exclude注解

@OneToOne
@PrimaryKeyJoinColumn
@Exclude
protected User user;
于 2013-09-27T20:18:32.657 回答
2

如果您不想UserBanned引用User,则可以将其设为UserBanned可嵌入并将其嵌入User.

@Embeddable
public class UserBanned{
    ....
}

@Entity
@Table(name = "user")
@DynamicInsert
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "user_id_generator")
    @SequenceGenerator(name = "user_id_generator", sequenceName = "user_id_seq")
    protected Integer id;

    @Column
    protected Integer name;

    @Embedded
    protected UserBanned userBanned;

如果您希望UserBanned位于单独的数据库表中,并且该表应包含对user-table 的引用,我认为您不能避免使用Userin UserBanned,否则 Hibernate 将不知道所指User的是哪个。UserBanned

如果您只想摆脱 line userBanned.setUser(user);,则可以将UserinUserBanned方法设置为Users setUserBanned(userBanned );

public void setUserBanned(UserBanned userBanned) {
    this.userBanned = userBanned;
    userBanned.user(this);
}

然后从序列化中排除该字段,例如以Ilyas answer中建议的方式。

于 2013-09-27T20:20:20.830 回答