Java 将对象作为查询参数传递并排除ID列
我有以下资料:Java 将对象作为查询参数传递并排除ID列,java,jpa,Java,Jpa,我有以下资料: @Entity @NamedQuery(name = "listCarsBySecurity", query = "SELECT c FROM Car c WHERE c.security = :security" public class Car { @Id @GeneratedValue private Long id; @NotNull() @Column(nullable = false) private Str
@Entity
@NamedQuery(name = "listCarsBySecurity", query = "SELECT c FROM Car c WHERE c.security = :security"
public class Car {
@Id
@GeneratedValue
private Long id;
@NotNull()
@Column(nullable = false)
private String make;
@NotNull()
@Column(nullable = false)
private String model;
// Some more fields
@NotNull()
@OneToOne (fetch = FetchType.LAZY, orphanRemoval=true)
private Security security = new Security();
// Some getters and setters
如您所见,Car类有一个“Security”对象,它是惰性获取的。安全类看起来像:
@Stateless
public class CarEJB {
@PersistenceContext(unitName = "carcmsPU")
private EntityManager em;
public List<Car> listCarsBySecurity(Security security) {
TypedQuery<Car> query = em.createNamedQuery("listCarsBySecurity", Car.class);
query.setParameter("security", security);
return query.getResultList();
}
@Test
public void searchCar() throws Exception {
// Looks up the EJBs
carEJB = (CarEJB) ctx.lookup("java:global/classes/CarEJB");
// Create a new Ferrari with security = ABS brakes and Airbag
Car car = new Car();
car.setMake("Ferrari");
car.setModel("Some model");
car.setSubModel("Some sub model");
car.setEngine("Some engine");
car.setYear(1999);
car.getFuel().setGasoline(true);
car.setGearbox(Gearbox.AUTOMATIC);
car.setKilometres(323);
car.setDescription("This is a description");
Security security = new Security();
security.setAbs(true);
security.setAirbag(true);
car.setSecurity(security);
carEJB.createCar(car); // Persist
// Create a new security object and match it to the former one
Security securityObject = new Security();
securityObject.setAbs(true);
securityObject.setAirbag(true);
List<Car> carList = carEJB.listCarsBySecurity(securityObject);
assertTrue("Should contain at least 1 car with ABS and Airbag", carList.size() > 0 );
for (Car carTemporary : carList) {
System.out.println(carTemporary.toString());
}
}
@实体
公共安全{
@Id @GeneratedValue
private Long id;
// Security equipment. Add in alphanumerical order
private boolean abs;
private boolean airbag;
private boolean antispin;
// Some getters and setters
如您所见,命名查询列表尝试列出所有具有与提供的安全对象相等的安全实体的汽车
持久性方法如下所示:
@Stateless
public class CarEJB {
@PersistenceContext(unitName = "carcmsPU")
private EntityManager em;
public List<Car> listCarsBySecurity(Security security) {
TypedQuery<Car> query = em.createNamedQuery("listCarsBySecurity", Car.class);
query.setParameter("security", security);
return query.getResultList();
}
@Test
public void searchCar() throws Exception {
// Looks up the EJBs
carEJB = (CarEJB) ctx.lookup("java:global/classes/CarEJB");
// Create a new Ferrari with security = ABS brakes and Airbag
Car car = new Car();
car.setMake("Ferrari");
car.setModel("Some model");
car.setSubModel("Some sub model");
car.setEngine("Some engine");
car.setYear(1999);
car.getFuel().setGasoline(true);
car.setGearbox(Gearbox.AUTOMATIC);
car.setKilometres(323);
car.setDescription("This is a description");
Security security = new Security();
security.setAbs(true);
security.setAirbag(true);
car.setSecurity(security);
carEJB.createCar(car); // Persist
// Create a new security object and match it to the former one
Security securityObject = new Security();
securityObject.setAbs(true);
securityObject.setAirbag(true);
List<Car> carList = carEJB.listCarsBySecurity(securityObject);
assertTrue("Should contain at least 1 car with ABS and Airbag", carList.size() > 0 );
for (Car carTemporary : carList) {
System.out.println(carTemporary.toString());
}
}
@无状态
公共类CarEJB{
@PersistenceContext(unitName=“carcmsPU”)
私人实体管理者;
公共列表列表CarsBySecurity(安全性){
TypedQuery query=em.createNamedQuery(“listCarsBySecurity”,Car.class);
query.setParameter(“security”,security);
返回query.getResultList();
}
junit测试如下所示:
@Stateless
public class CarEJB {
@PersistenceContext(unitName = "carcmsPU")
private EntityManager em;
public List<Car> listCarsBySecurity(Security security) {
TypedQuery<Car> query = em.createNamedQuery("listCarsBySecurity", Car.class);
query.setParameter("security", security);
return query.getResultList();
}
@Test
public void searchCar() throws Exception {
// Looks up the EJBs
carEJB = (CarEJB) ctx.lookup("java:global/classes/CarEJB");
// Create a new Ferrari with security = ABS brakes and Airbag
Car car = new Car();
car.setMake("Ferrari");
car.setModel("Some model");
car.setSubModel("Some sub model");
car.setEngine("Some engine");
car.setYear(1999);
car.getFuel().setGasoline(true);
car.setGearbox(Gearbox.AUTOMATIC);
car.setKilometres(323);
car.setDescription("This is a description");
Security security = new Security();
security.setAbs(true);
security.setAirbag(true);
car.setSecurity(security);
carEJB.createCar(car); // Persist
// Create a new security object and match it to the former one
Security securityObject = new Security();
securityObject.setAbs(true);
securityObject.setAirbag(true);
List<Car> carList = carEJB.listCarsBySecurity(securityObject);
assertTrue("Should contain at least 1 car with ABS and Airbag", carList.size() > 0 );
for (Car carTemporary : carList) {
System.out.println(carTemporary.toString());
}
}
@测试
public void searchCar()引发异常{
//查找EJB
carEJB=(carEJB)ctx.lookup(“java:global/classes/carEJB”);
//创建一个新的法拉利与安全=ABS刹车和安全气囊
汽车=新车();
汽车制造(“法拉利”);
汽车模型(“某些模型”);
car.setSubModel(“某个子模型”);
设置引擎(“某个引擎”);
car.设定年份(1999年);
car.getFuel().set汽油(true);
汽车。设置变速箱(变速箱。自动);
汽车行驶里程(323公里);
car.setDescription(“这是一个描述”);
安全性=新安全性();
security.setAbs(true);
安全性。设置安全气囊(true);
车辆设置安全性(安全性);
carEJB.createCar(car);//持续
//创建一个新的安全对象并将其与前一个匹配
Security securityObject=new Security();
securityObject.setAbs(true);
securityObject.setAirbag(true);
List carList=carEJB.listCarsBySecurity(securityObject);
assertTrue(“应至少包含一辆带ABS和安全气囊的汽车”,carList.size()>0);
对于(汽车卡特尔当代人:carList){
System.out.println(cartemporal.toString());
}
}
问题是列表中根本不包含任何汽车。我想我知道为什么;命名查询会尝试将security_id与NULL匹配(因为我没有定义它)
我的问题是:如何通过将对象作为没有ID的查询参数传递,以及不指定该对象内部要比较的所有字段来执行查询?(或者如何从搜索中排除ID)
致以最诚挚的问候您可以使用或定义命名查询,并传递对象的每个属性。您还可以使用Criteria API根据要查询的字段生成查询。由于您已经有了命名查询,我将把它留给您 如果你决定这样做(如果你的实体有太多的属性,那么严格的逐字段比较有点疯狂)
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> query = builder.createQuery(Car.class);
Root<Car> queryRoot = query.from(Car.class);
query.select(queryRoot);
Path<String> pathToYourField = root.get(yourField); //yourField is a variable containing the field.
//You can store all the variables in a list, iterate
//over them and do this for each one.
query.where(builder.and(builder.equal(pathToYourField, "particularValue"))); //You compare the path against a value.
//Rest of the fields / paths
TypedQuery<Car> typedQuery = entityManager.createQuery(query);
List<Car> cars = typedQuery.getResultList();
CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery=builder.createQuery(Car.class);
Root queryRoot=query.from(Car.class);
query.select(queryRoot);
Path pathToYourField=root.get(yourField);//yourField是包含该字段的变量。
//您可以将所有变量存储在一个列表中,迭代
//在他们身上,每个人都这样做。
query.where(builder.and(builder.equal(pathToYourField,“SpecificularValue”);//将路径与值进行比较。
//其余字段/路径
TypedQuery TypedQuery=entityManager.createQuery(查询);
List cars=typedQuery.getResultList();
编辑:关于性能,请查看以下链接:
您可以使用或定义命名查询,并传递对象的每个属性。您还可以使用Criteria API根据要查询的字段生成查询。由于您已经有一个命名查询,我将把它留给您 如果你决定这样做(如果你的实体有太多的属性,那么严格的逐字段比较有点疯狂)
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> query = builder.createQuery(Car.class);
Root<Car> queryRoot = query.from(Car.class);
query.select(queryRoot);
Path<String> pathToYourField = root.get(yourField); //yourField is a variable containing the field.
//You can store all the variables in a list, iterate
//over them and do this for each one.
query.where(builder.and(builder.equal(pathToYourField, "particularValue"))); //You compare the path against a value.
//Rest of the fields / paths
TypedQuery<Car> typedQuery = entityManager.createQuery(query);
List<Car> cars = typedQuery.getResultList();
CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery=builder.createQuery(Car.class);
Root queryRoot=query.from(Car.class);
query.select(queryRoot);
Path pathToYourField=root.get(yourField);//yourField是包含该字段的变量。
//您可以将所有变量存储在一个列表中,迭代
//在他们身上,每个人都这样做。
query.where(builder.and(builder.equal(pathToYourField,“SpecificularValue”);//将路径与值进行比较。
//其余字段/路径
TypedQuery TypedQuery=entityManager.createQuery(查询);
List cars=typedQuery.getResultList();
编辑:关于性能,请查看以下链接:
您好,谢谢您的回答!我认为您的解决方案对我的应用程序来说会很好,除了性能之外。前端是一个AJAX网页,将执行大量查询。对于安全类中的20个字段来说,使用此解决方案是否会造成很大的性能损失?Criteria API最适合动态查询。如果您发现自己使用的是g通常,你可以考虑将它命名为NoQudQuess。在性能方面,标准可能会慢一些,但到最后,据我所知,没有什么有意义的区别。我已经添加了一些链接到我的答案,其中有一些有趣的文章。嗨,谢谢你的回答!我认为你的解决方案会很好。对于我的应用程序,除了性能之外,前端是一个Ajax网页,它将执行大量的查询。使用这个解决方案会有很大的性能损失,比如说在安全类中有20个字段。标准API在动态查询中是最有效的。如果你发现自己经常使用生成的查询,你可以考虑将它命名为NoqQueor。相反,在性能方面,标准可能是