简体   繁体   English

Hibernate One-To-One关系

[英]Hibernate One-To-One relationship

I see many turoials and articles about subject, but i can't understand one thing. 我看到许多有关主题的语言和文章,但我无法理解一件事。 For a example: i have "User" table with fields "id", "name" and i have "UserBanned" table with fields "userid" and "reason". 例如:我有“用户”表,字段为“id”,“name”,我有“UserBanned”表,字段为“userid”和“reason”。 UserBanned.userid - it is link (foreign key) on field User.id. UserBanned.userid - 它是字段User.id上的链接(外键)。

So, models in hiberante looks like: 因此,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;

And UserBanned model: 和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;

And it works. 它有效。 I can create new user and banned user with this code: 我可以使用以下代码创建新用户和禁止用户:

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

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

    clientService.store(user);

But, when i try to do gson.toJson(client) i got stackoverflow error - because Gson can't handle circular references in the serialized data. 但是,当我尝试做gson.toJson(客户端)时,我得到了stackoverflow错误 - 因为Gson无法处理序列化数据中的循环引用。 But my mind cant understand why i have to set User in UserBanned?! 但我的想法无法理解为什么我必须在UserBanned中设置用户?! Why i can not just have model User? 为什么我不能只拥有模特用户?

My question: how i can organize such relationship (One-To-One with foreign key) like User (there are not only UserBanned, but and UserVIP and etc entities) in hibernate? 我的问题:如何在hibernate中组织这样的关系(一对一与外键),如User(不仅有UserBanned,还有UserVIP和其他实体)?

You should exclude one of cycled references ( User::userBanned or UserBanned::user ) from serialization and deserialization by Gson . 您应该从Gson序列化和反序列化中排除一个循环引用( User::userBannedUserBanned::user )。
You can read about it in gson-documentation . 你可以在gson文档中阅读它。

Add some annotation 添加一些注释

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

Create ExclusionStrategy 创建ExclusionStrategy

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

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

Create Gson instance with GsonBuilder 使用GsonBuilder创建Gson实例

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

Annotate UserBanned::user with @Exclude annotation 使用@Exclude批注对UserBanned::user进行批注

@OneToOne
@PrimaryKeyJoinColumn
@Exclude
protected User user;

If you don't want UserBanned to have reference to User , you could make the UserBanned embeddable and embed it in User . 如果您不希望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;

If you want the UserBanned to be in separate database-table and the table should contain reference to the user -table, I don't think you can avoid having the User in UserBanned , otherwise Hibernate won't know which User the UserBanned refers to. 如果你想让UserBanned在单独的数据库表中并且表应该包含对user表的引用,我认为你不能避免在UserBanned中使用User ,否则Hibernate将不知道UserBanned引用哪个User

If you want just to get rid of the line userBanned.setUser(user); 如果你想要摆脱userBanned.setUser(user); , you could set the User to UserBanned in Users setUserBanned(userBanned ); ,你可以设置UserUserBannedUsers setUserBanned(userBanned ); -method. -方法。

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

And then excluding the field from serialization for example in way suggested in Ilyas answer . 然后从序列化中排除字段,例如在Ilyas答案中建议的方式。

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

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