【问题标题】:Pass a object as query parameter and exclude the ID column将对象作为查询参数传递并排除 ID 列
【发布时间】:2012-08-01 17:09:20
【问题描述】:

我有以下几点:

@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”对象,该对象是 LAZY 获取的。安全类如下所示:

@实体 公共类安全 {

@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();
    }

一个junit测试看起来像:

@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());

    }



}

问题是该列表根本不包含任何汽车。我想我知道为什么;命名查询确实尝试将 security_id 与 NULL 匹配(因为我没有定义它)。

我的问题是:如何通过将对象作为没有 ID 的查询参数传递并且不指定应在该对象内进行比较的所有字段来执行查询? (或者如何从搜索中排除 ID)?

最好的问候

【问题讨论】:

    标签: java jpa


    【解决方案1】:

    您可以使用 OR 定义命名查询并传递对象的每个属性。您还可以使用 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();
    

    编辑:关于性能,请查看以下链接:

    1. JPA Criteria vs NamedQueries
    2. Another answer regarding Criteria vs HQL
    3. Criteria overhead discussion

    【讨论】:

    • 您好,感谢您的回答!我认为您的解决方案对我的应用程序很有效,但性能可能除外。前端是一个 AJAX 网页,会执行很多查询。对于安全类中的 20 个字段,使用此解决方案是否会造成很大的性能损失?
    • Criteria API 最适合动态查询。如果您发现自己经常使用生成的查询,则可以考虑将其改为 NamedQuery。在性能方面,Criteria 可能会慢几毫秒,但据我所知,最终没有显着差异。我在我的答案中添加了一些链接以及一些关于它的有趣文章。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    • 2021-12-25
    • 2020-10-06
    • 1970-01-01
    相关资源
    最近更新 更多