Java Eclipse hibernate pojo生成包含外键

Java Eclipse hibernate pojo生成包含外键,java,eclipse,hibernate,foreign-keys,hibernate-tools,Java,Eclipse,Hibernate,Foreign Keys,Hibernate Tools,我一直遵循使用hibernate从mysql数据库生成POJO的优秀指南。您可以在此处找到指南以供参考: 我得到了一个POJO,当外键存在时,该POJO具有嵌入其他对象的字段。例如,用户的地址。Hibernate正在生成如下内容: public class User(){ private String name; private Integer uid; private Address address; } 但是,我有一个问题,我希望类实际包含外键值。例如,我希望用户对象有一个与add

我一直遵循使用hibernate从mysql数据库生成POJO的优秀指南。您可以在此处找到指南以供参考:

我得到了一个POJO,当外键存在时,该POJO具有嵌入其他对象的字段。例如,用户的地址。Hibernate正在生成如下内容:

public class User(){
 private String name;
 private Integer uid;
 private Address address;
}
但是,我有一个问题,我希望类实际包含外键值。例如,我希望用户对象有一个与addressId的数据库字段相对应的类字段。所以,我想让对象看起来像这样:

public class User(){
 private String name;
 private Integer uid;
 private Integer addressId;
 private Address address;
}
有人知道如何修改hibernate代码生成过程,以便在对象上包含外键值作为字段吗

更新: 我发现了一篇SO帖子,它描述了如何忽略外键关系,只获取外键作为类字段:

这里的问题是我两者都想要。我不想忽视这些关系。我想要表示它们,但我也想要实际的外键值

更新:

让我更具体地说明为什么我需要这个解决方案。我们正在尝试序列化这些hibernate对象。现在,我们有很多不同的hibernate POJO正在进行反向工程。我们不希望为每个类手动编写序列化例程。如果我们遵循“只需手动将访问方法写入嵌入对象上的外键字段”的约定,就必须这样做。此外,即使我们这样做,pojo仍然不知道外键字段的名称。相反,我们将gson与类型适配器一起使用

使用gson,我们序列化pojo上的所有字段,而忽略包含hibernate对象的字段。当然,问题是我们没有外键字段。这里我们需要一些信息,以便一般地序列化任何hibernate pojo。我们需要知道:

  • 外键字段名
  • 外键字段值

  • 您的方法将导致类的数据冗余。在Hibernate生成的第一组代码中,您可以从用户类的Address属性获取所需的addressId:

    yourUser.getAddress().getAddressId();
    

    您的方法违反了Hibernate约定。因为Hibernate使用反射,所以约定是Hibernate完成其工作所必需的。因此,我怀疑Maouven的“遵循惯例”方法是最简单的。但是,如果不可协商,您有两个选择

    第一个选项是添加临时getter,以公开getAddressId()函数

    public class User() {
        private String name;
        private Integer uid;
        private Address address;
    
        // Getters, setters...
    
        @Transient
        public boolean getAddressId() {
            address.getId();
        }
    }
    
    第二个选项是添加一个数据访问层,在Hibernate对象之上强加您自己的约定。这一抽象层将不受Hibernate约定的约束。这样,POJO将由DAOs()包装,您可以根据需要进行设计

    更新:

    给定您的唯一情况,考虑修改序列化步骤。GSON通常不能使用瞬态方法,但有一个扩展可以使用,如图所示

    另一种解决方案是使用反射以您想要的方式复制对象,然后使用GSON序列化复制的对象。

    两种可能的(理论上讲)解决方案,但在通过Hibernate工具进行反向工程后需要手动重构:

    我使用注释只是为了简洁

    1) 使用映射公开列:

    @Entity
    class User
    {
        @Id
        @Column
        private Integer uid;
    
        @Column
        private String name;
    
        @Column(name = "ADDRESS_ID", insertable = false, updatable = false)
        private Integer addressId;
    
        @ManyToOne
        @JoinColumn(name = "ADDRESS_ID")
        private Address address;
    }
    
    2) 使用@Transient+@PostLoad:

    @Entity
    class User
    {
        @Id
        @Column
        private Integer uid;
    
        @Column
        private String name;
    
        @Transient
        private Integer addressId;
    
        @ManyToOne
        @JoinColumn(name = "ADDRESS_ID")
        private Address address;
    
        @PostLoad
        public void postLoad()
        {
            addressId = Optional.ofNullable(address).map(Address::getId).orElse(null);
        }
    }
    
    使用JSON marshaller for JAXB可能会有另一种解决方案:

    @XmlRootElement
    class User
    {
        @XmlID
        private Integer uid;
    
        private String name;
    
        @XmlIDREF
        private Address address;
    }
    

    您可以找到一个快速启动

    我确实意识到相同的信息被编码了两次,一次作为外键,一次作为唯一id。我发现在对象上保存数据的便利性值得在非常小的内存占用之间折衷。明确提到外键使编写通用方法变得更容易。出于序列化目的,系统仍然不知道外键的字段名。我写了一个更新来解释我们的特定用例,只是为了帮助理解上下文。令我惊讶的是,hibernate社区中有很大一部分人没有遇到这个问题。当然,人们不会坐下来手动编写/维护几十个(如果不是几百个)序列化例程?关于DAO包装器,我该如何将外键字段名和值放入这样一个对象中?这里有一个类似的问题,它只是上一层。谢谢你的更新。就个人而言,我们有单独的POJO进行序列化,我们有复制构造函数来填充它们。这避免了两个自以为是的库试图在同一对象上使用反射的问题。DAO包装器以类似的方式避免了该问题。额外的一层允许每个自以为是的库以它想要的方式使用反射。这同样不是自动化的,所以对您来说可能不是一个好的解决方案。关于您的更新,这不需要为每个类编写一个自定义序列化程序,然后向gson注册吗?如果是这样的话,这就不太容易维护了。