问题
I have been following an excellent guide for generating pojos from a mysql database using hibernate. One can find the guide here for reference: Generate pojos with hibernate
I am getting pojos which have fields that embed other objects when a foreign key was present. For example, user's have addresses. Hibernate is generating something like the following:
public class User(){
private String name;
private Integer uid;
private Address address;
}
I have a problem, though, in that I want the classes to actually contain the foreign key value. For example, I want the User object to have a class field corresponding to the database field for addressId. So, I want the object to actually look something like this:
public class User(){
private String name;
private Integer uid;
private Integer addressId;
private Address address;
}
Does anyone know how to modify the hibernate code generation process so as to include foreign key values as fields on the object?
Update: I found a SO post which describes how to ignore the foreign key relationships and just get foreign keys as class fields: How to ignore foreign keys?
The problem here is that I want both. I don't want to ignore the relationships. I want them represented, but I also want the actual foreign key values.
Update:
Let me be more specific as to why I want this solution. We are trying to serialize these hibernate objects. Now, we have a lot of different hibernate pojos which are being reverse engineered. We do not want to manually write a serialization routine for every class. We would have to do that if we followed the convention of "just manually write an access method to the foreign key field on the embedded object". Further, even if we were to do so, the pojo still doesn't know what the field of the foreign key is called. Instead, we are using gson with a type adaptor.
With gson, we are serializing all fields on the pojo and just ignoring fields that contain a hibernate object. The problem, of course, is that we don't have the foreign key fields. We need a few pieces of information here in order to generically serialize any hibernate pojo. We need to know:
- The foreign key field name
- The foreign key field value
回答1:
Your approach violates Hibernate convention. Because Hibernate uses reflection, convention is essential for Hibernate to do it's job. Because of this, I suspect Maouven's "follow the convention" approach is easiest. However, if it is non-negotiable, you have two options available.
Your first option is to add a transient getter, to expose the getAddressId() function.
public class User() {
private String name;
private Integer uid;
private Address address;
// Getters, setters...
@Transient
public boolean getAddressId() {
address.getId();
}
}
Your second option is to add a Data Access layer to impose your own conventions on top of Hibernate objects. This layer of abstraction will not be bound by Hibernate's conventions. This way, your POJOs will be wrapped by DAOs (Data Access Objects), which you can design as you see fit.
Update:
Given your unique case, consider modifying your serialization step. GSON normally can't use transient methods, but there is an extension that can do this, as shown here.
Another solution would be to use reflection to copy the object the way you want it, and then use GSON to serialize the copied object.
回答2:
Your approach will cause redundancy in the class's data. In the first bunch of code -generated by Hibernate-, you can get the addressId you need from the Address property of the User Class :
yourUser.getAddress().getAddressId();
回答3:
Two possible (theoretically speaking) solutions, but require manual refactoring after reverse engineering by Hibernate Tools:
I'm using annotations just for brevity
1) expose the column with mapping:
@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) use @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);
}
}
Another solution could be possible using JSON marshaller for JAXB:
@XmlRootElement
class User
{
@XmlID
private Integer uid;
private String name;
@XmlIDREF
private Address address;
}
You can find a quickstart here
来源:https://stackoverflow.com/questions/34301634/eclipse-hibernate-pojo-generation-include-foreign-keys