简体   繁体   中英

JPA/Hibernate how to join a particular field from an entity into a different entity

Assuming we have Entity A and Entity B, each with its corresponding table, A and B.

Entity A is a Hotel and has an ID and several fields such as Country, City, PostalCode, etc.

Entity B is a Description List has an ID (which is the same with the one in Entity A) and another 2 fields, Language and Description.

I'm making the following query in my DAO:

    Query query = getEntityManager().createQuery("FROM " + type.getSimpleName() +
            " WHERE City = :cityParam AND Country = :countryParam");
    query.setParameter("cityParam", cityParam);
    query.setParameter("countryParam", countryNameParam);
    query.setMaxResults(numberOfResults);
    List<HotelDto> hotelMap = query.getResultList();
    ListResponseModel result = new ListResponseModel();
    result.setHotelMap(hotelMap);
    return result.getHotelMap().size() > 0 ? result : null;

Entity A, the Hotel Entity looks like this:

@Entity
@Table(name = "propertyList", uniqueConstraints = 
{ @UniqueConstraint(columnNames = "HotelID")})
public class Hotel implements Serializable, EntityWithId<Long> {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
@Column(name = "HotelID")
private Long hotelId;

@Column(name = "Name")
private String name;

@Column(name = "Address")
private String address;

@Column(name = "City")
private String city;

@Column(name = "StateProvince")
private String stateProvince;

@Column(name = "PostalCode")
private String postalCode;

@Column(name = "Country")
private String country;

@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "propertyhotelid")
private PropertyDescription propertyDescription;
[...]

Entity B, the Description, looks like this:

@Entity
@Table(name = "propertyDescriptionList", uniqueConstraints = 
{ @UniqueConstraint(columnNames = "HotelID")})
public class PropertyDescription implements Serializable, EntityWithId<Long> {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "HotelID", unique = true, nullable = false)
private Long hotelId;

@Column(name = "PropertyDescription")
private String propertyDescription;

The issue is that once I get the result set, a single entity would look like this:

hotelId: 124125,
name: "Random Hotel",
address: "Some Address",
city: "Shambala",
postalCode: "W2 3NA",
country: "Nevereverland",
-propertyDescription: {
    hotelId: 105496,
    propertyDescription: "Insert Description here bla bla bla."
}
}

What I want to get is this:

hotelId: 124125,
name: "Random Hotel",
address: "Some Address",
city: "Shambala",
postalCode: "W2 3NA",
country: "Nevereverland",
propertyDescription: "Insert Description here bla bla bla."
}

Since I'm only interested in the Description itself which is a String, and not in having the entire Object which also has the ID (a duplicate).

What would be the best approach to achieve this ?

From your question is sounds like what you are looking for is a way to map two tables to one entity? If so you can do this with @SecondaryTable: the String 'description' then will simply become a field of your Hotel entity.

@Entity
@Table(name = "propertyList", uniqueConstraints = { @UniqueConstraint(columnNames = "HotelID") })
@SecondaryTable(name = "propertyDescriptionList", pkJoinColumns = @PrimaryKeyJoinColumn(name = "HotelID"), uniqueConstraints = { @UniqueConstraint(columnNames = "HotelID") })
public class Hotel implements Serializable {

    @Id
    @Column(name = "HotelID")
    private Long hotelId;

    @Column(name = "PropertyDescription", table = "propertyDescriptionList")
    private String propertyDescription;

}

You can use JPQL constructor expressions , and have something like this

"select new my.package.HotelDTO(h) from Hotel h where ..."

And you will need a field String propertyDescription and a constructor in HotelDTO

public HotelDTO(Hotel hotel) {
    ...
    this.propertyDescription = hotel.getPropertyDescription().getPropertyDescription();
    ...
}

Why not have it as a lazily fetched field instead?

@Basic(fetch = FetchType.LAZY)
private String propertyDescription;

That way it is not fetched unless specifically asked for, and you get it as a String field in the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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