1

私は次のものを持っています:

@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 クラスには、LAZY フェッチされる「Security」オブジェクトがあります。セキュリティ クラスは次のようになります。

@Entity パブリック クラス セキュリティ {

@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 を除外する方法)?

よろしくお願いします

4

1 に答える 1

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基準とNamedQueries
  2. 基準とHQLに関する別の回答
  3. 基準オーバーヘッドディスカッション
于 2012-08-03T16:22:19.330 に答える