如何编写规范连接两个表,其中属性在不同的类中

时间:2021-07-05 15:25:15

Boot Application and need a query with dynamic where field. Googling about it I've found Specifications could be an answer but how a make the where clause searching in attributes in different classes?

启动应用程序并需要具有动态where字段的查询。谷歌搜索我发现规格可能是一个答案,但如何使where子句在不同的类中搜索属性?

Here's my model

这是我的模特

Brand Class

品牌类

@Entity
public class Brand {

@Id
private Long id;

private String name;

@OneToMany(mappedBy="brand",cascade=CascadeType.ALL)
private Set<Cars> cars;
//Getter's and Setters
}

Car Class

汽车类

@Entity
public class Car {

@Id
private Long id;
private String name;
private String carType;

@ManyToOne(cascade=CascadeType.ALL)
private brand brand;
//Getter's and Setters
}

The repository is the strait one:

存储库是海峡的:

public interface CarRepository extends JpaRepository<Car, Long>, JpaSpecificationExecutor<Car> {    
}

If the user enters the car's name and the brand i need something like the following jpql

如果用户输入汽车的名称和品牌我需要类似下面的jpql

 select c from car c join c.brand br where br.name = :brandName and c.name = :carName

Also the user can enter only with the type of the car, so the jpql will be:

用户也可以只输入汽车的类型,所以jpql将是:

select c from car c join c.brand br where br.name = :brandName and c.carType = :carType

1 个解决方案

#1


0  

Specifications are commonly used when you need to build dynamic queries. If your use case is limited to those two queries, I would rather write those as static queries and have a simple if/else to check if the name or type was provided.

当您需要构建动态查询时,通常会使用规范。如果您的用例仅限于这两个查询,我宁愿将它们写为静态查询,并使用简单的if / else检查是否提供了名称或类型。

When you use specifications and you follow the Spring guides, you should write an additional class that has your various specifications, for example:

当您使用规范并遵循Spring指南时,您应该编写一个具有各种规范的附加类,例如:

public class CarSpecifications {
    public static Specification<Car> withBrandName(final String name) {
        return (root, query, cb) -> {
            final Path<Brand> brandPath = root.get("brand");
            return cb.equal(brandPath.<String>get("name"), name);
        };
    }

    // TODO: withName, withType
}

You'll have to add multiple methods here, the method above is only for your br.name = :brandName clause.

您必须在此处添加多个方法,上述方法仅适用于您的br.name =:brandName子句。

Now, to use this class you have to write something like:

现在,要使用这个类,你必须写下这样的东西:

public List<Car> findCars(String brandName, String name, String type) {
    Specifications<Car> spec = Specifications
        .<>where(CarSpecifications.withBrandName(brandName));
    if (name != null) {
        spec.and(CarSpecifications.withName(name);
    }
    // TODO: if (type != null) ...

    return repository.findAll(spec);
}

#1


0  

Specifications are commonly used when you need to build dynamic queries. If your use case is limited to those two queries, I would rather write those as static queries and have a simple if/else to check if the name or type was provided.

当您需要构建动态查询时,通常会使用规范。如果您的用例仅限于这两个查询,我宁愿将它们写为静态查询,并使用简单的if / else检查是否提供了名称或类型。

When you use specifications and you follow the Spring guides, you should write an additional class that has your various specifications, for example:

当您使用规范并遵循Spring指南时,您应该编写一个具有各种规范的附加类,例如:

public class CarSpecifications {
    public static Specification<Car> withBrandName(final String name) {
        return (root, query, cb) -> {
            final Path<Brand> brandPath = root.get("brand");
            return cb.equal(brandPath.<String>get("name"), name);
        };
    }

    // TODO: withName, withType
}

You'll have to add multiple methods here, the method above is only for your br.name = :brandName clause.

您必须在此处添加多个方法,上述方法仅适用于您的br.name =:brandName子句。

Now, to use this class you have to write something like:

现在,要使用这个类,你必须写下这样的东西:

public List<Car> findCars(String brandName, String name, String type) {
    Specifications<Car> spec = Specifications
        .<>where(CarSpecifications.withBrandName(brandName));
    if (name != null) {
        spec.and(CarSpecifications.withName(name);
    }
    // TODO: if (type != null) ...

    return repository.findAll(spec);
}