当该列属于Spring中的复合主键时如何按一列过滤
Posted
技术标签:
【中文标题】当该列属于Spring中的复合主键时如何按一列过滤【英文标题】:How to filter by one column when that column belongs to a composite primary key in Spring 【发布时间】:2019-05-11 21:05:45 【问题描述】:拥有这样的 DAO:
@Entity
@Table(name="booking")
public class BookingObject implements Serializable
private static final long serialVersionUID = 1L;
@EmbeddedId
private CompositeId compositePK;
private LocalDate init_date;
private LocalDate end_date;
private int confirmation;
// getters and setters
和复合主键:
@Embeddable
public class CompositeId implements Serializable
private static final long serialVersionUID = 1L;
@NotNull
private String guest;
@NotNull
private String idhousing;
//getters and setters
所以我现在可以从我的@RestController
拨打findById(new CompositeId(guest, idhousing));
。
问题是:如果我想按复合主键的列之一进行过滤,比如 guest。
我不能这样做 findByguest
,因为我的 DAO BookingObject
中不再存在来宾。我怎样才能得到“给我所有来宾等于...的行”的结果
【问题讨论】:
select b from BookingObject b where b.compositePK.guest = :guest
。确实,真的,您应该避免使用复合函数 ID 并使用自动生成的技术 ID。
@JBNizet 和自动生成的 ID 会生成复合主键吗?
不,我的意思是您应该避免使用复合函数 ID。
@JBNizet 问题是,如果没有复合主键 guest 和 id_house,我将无法多次预订一个特定的房子。想象客人是主键。那么一个用户不能预订多于一个房子,这不符合逻辑,因为他可以预订下周的房子,下个月的另一个。另一方面,如果 id_house 是主键,则不能多次预订。房子可以在下周和一年内预订。希望你能理解我的问题。
我从来没有建议你使用guest或house作为PK。我建议使用自动生成的技术 ID。顺便说一句,你的 PK 设计是错误的:同一个客人不能在两个不同的日期预订同一个房子,因为 [guest, house] 是 PK,因此必须是唯一的。
【参考方案1】:
另一种方法是创建autoincremental key
。它是一个整数,当在表中插入新行时会自动递增。这样就不需要复合主键了。唯一的问题是用户可以在同一日期无限次预订同一所房子。但是可以在您的 servlet 中实现一些逻辑,以检查该用户是否已经预订了该房子。
参考:w3schools autoincrement
【讨论】:
【参考方案2】:你可以试试 findByExample
CompositeId compId= new CompositeId();
compId.setGuest(guestVal);
BookingObject bookingObj= new BookingObject ();
bookingObj.setCompositeId(compId);
Example<BookingObject> bookExample = Example.of(bookingObj);
List<BookingObject> objList=repository.findAll(bookExample);
【讨论】:
【参考方案3】:您可以通过在存储库类中声明一个查询方法来做到这一点,例如
List<BookingObject> findByCompositePKGuest(String guest);
并使用此方法从您的控制器获取数据。
该方法以标准 JPA 格式编写。方法名称被解析为对象和字段的概念,并在后台转换为实际的 SQL 查询。
更多参数是这样的
List<BookingObject> findByCompositePKGuestAndCompositePKIdhousing(String guest, String idhousing);
findByCompositePKGuestAndCompositePKIdhousing
转换为 -> findBy + compositePK.guest + And + compositePK.idhousing
另一种选择是通过示例使用 Spring JPA 过滤器
在存储库类中声明findAll(Example)
方法
List<BookingObject> findAll(Example<BookingObject> bookingObject);
然后像这样从控制器调用这个方法
BookingObject bookingObject = new BookingObject();
CompositeId compositeId = new CompositeId();
compositeId.setGuest(guest);
bookingObject.setCompositeId(compositeId);
Example<BookingObject> bookingObjectExample = Example.of(bookingObject);
List<BookingObject> bookingObjectList = bookingRepository.findAll(bookingObjectExample);
请参阅此link 以获得更详细的答案
【讨论】:
以上是关于当该列属于Spring中的复合主键时如何按一列过滤的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate:insertable = false,updatable = false 属于涉及外键的复合主键星座中的哪里?