Java JPA 2.1带条件的多连接

Java JPA 2.1带条件的多连接,java,jpa,left-join,criteria-api,Java,Jpa,Left Join,Criteria Api,我将java EE7与JPA 2.1结合使用,并尝试进行如下查询: select generatedAlias0, count(generatedAlias1), count(generatedAlias2) from Accounts as generatedAlias0 left join items as generatedAlias1 on ( generatedAlias1.creator_id=generatedAlias0.id ) and ( generatedAlias1

我将java EE7与JPA 2.1结合使用,并尝试进行如下查询:

select generatedAlias0, count(generatedAlias1), count(generatedAlias2) 
from Accounts as generatedAlias0 
left join items as generatedAlias1 
on ( generatedAlias1.creator_id=generatedAlias0.id ) and ( generatedAlias1.status='CLOSED' )
 left join items as generatedAlias2 
 on  ( generatedAlias2.creator_id=generatedAlias0.id ) and ( generatedAlias2.status='OPEN' )
 where 1=1 group by generatedAlias0.id.
我拥有以下实体:

@Entity
@Table( name = "accounts" )

public class Account 
{
    @Id
    @GeneratedValue( generator = "acct_seq" )
    @SequenceGenerator( name = "acct_seq", sequenceName =    "accounts_id_seq", allocationSize = 1 )
    private Long id;

    @OneToMany( fetch = FetchType.LAZY )
    @OrderBy( "id desc" )
    @JoinTable( name = "items", joinColumns = @JoinColumn( name = "creator_id", referencedColumnName = "id" ), inverseJoinColumns =   @JoinColumn( name = "id", referencedColumnName = "id" ) )
    private List<Item> items;

    ... 

}
@实体
@表(name=“账户”)
公共类帐户
{
@身份证
@生成值(generator=“acct_seq”)
@SequenceGenerator(name=“acct\u seq”,sequenceName=“accounts\u id\u seq”,allocationSize=1)
私人长id;
@OneToMany(fetch=FetchType.LAZY)
@订购人(“id描述”)
@JoinTable(name=“items”,joinColumns=@JoinColumn(name=“creator\u id”,referencedColumnName=“id”),inverseJoinColumns=@JoinColumn(name=“id”,referencedColumnName=“id”))
私人清单项目;
... 
}
使用以下方法创建查询:

   public List<AccountDTO> findAccounts( int first, int pageSize, String sortField, String sortOrder,
        Map<String, Object> filters )
{
CriteriaBuilder builder = em.getCriteriaBuilder( );
CriteriaQuery<Tuple> criteriaQuery = builder.createTupleQuery( );
Root<Account> root = criteriaQuery.from( Account.class );
Join<Account, Item> itemsPlaced = root.join( "items", JoinType.LEFT );
Join<Account, Item> itemsSold = root.join( "items", JoinType.LEFT );

List<Predicate> itemsPlacedConditions = new ArrayList<>( );
itemsPlacedConditions.add( builder.equal( itemsPlaced.get( "creator" ).get( "id" ), root.get( "id" ) ) );
itemsPlacedConditions.add( builder.equal( itemsPlaced.get( "status" ), "OPEN" ) );

itemsPlaced.on( itemsPlacedConditions.toArray( new Predicate[] {} ) );
List<Predicate> itemsSoldConditions = new ArrayList<>( );

itemsSoldConditions.add( builder.equal( itemsSold.get( "owner" ), root ) );
itemsSoldConditions.add( builder.equal( itemsSold.get( "status" ), "CLOSED" ) );

itemsSold.on( itemsSoldConditions.toArray( new Predicate[] {} ) );


Expression<Long> countPlaced = builder.count( itemsPlaced );
Expression<Long> countSold = builder.count( itemsSold );

criteriaQuery
        .select( builder.tuple( root, countPlaced.alias( "itemsPlaced" ), countSold.alias( "itemsSold" ) ) );
if ( filters.containsKey( "fullName" ) )
{
    criteriaQuery.where( getOrPredicate( filters, builder, root ) );
}

criteriaQuery.where( getAndPredicate( filters, builder, root, itemsPlaced ) );

List<Order> orderList = new ArrayList<>( );

if ( sortField != null )
{
    orderList.add( sortOrder.equals( ASCENDING.value( ) ) ? builder.asc( root.get( sortField ) )
            : builder.desc( root.get( sortField ) ) );
} else
{
    orderList.add( builder.asc( root.get( "id" ) ) );
}
orderList.add( builder.desc( countPlaced ) );
criteriaQuery.groupBy( root.get( "id" ) );

List<Tuple> result = em.createQuery( criteriaQuery ).setFirstResult( first ).setMaxResults( pageSize )
        .getResultList( );
List<AccountDTO> accts = new ArrayList<>( );
for ( Tuple tuple : result )
{
    AccountDTO res = new AccountDTO( );
    try
    {
        res = ReflectionUtil.copy( AccountDTO.class, tuple.get( 0 ) );
    } catch (Exception e)
    {
        e.printStackTrace( );
    }
    res.setItemsPlaced( (Long) tuple.get( 1 ) );
    res.setItemsSold( (Long) tuple.get( 2 ) );
    accts.add( res );
}
return accts;
public List findAccounts(int first、int pageSize、String sortField、String sortOrder、,
地图过滤器)
{
CriteriaBuilder=em.getCriteriaBuilder();
CriteriaQuery-CriteriaQuery=builder.createTupleQuery();
Root=criteriaQuery.from(Account.class);
Join itemsPlaced=root.Join(“items”,JoinType.LEFT);
Join itemsSold=root.Join(“items”,JoinType.LEFT);
List itemsPlacedConditions=new ArrayList();
add(builder.equal(itemsPlaced.get(“creator”).get(“id”)、root.get(“id”));
添加(builder.equal(itemsPlaced.get(“status”),“OPEN”);
on(itemsPlacedConditions.toArray(新谓词[]{}));
List itemsSoldConditions=new ArrayList();
add(builder.equal(itemsSold.get(“所有者”),root));
add(builder.equal(itemsSold.get(“status”),“CLOSED”);
on(itemsSoldConditions.toArray(新谓词[]{}));
表达式countPlaced=builder.count(itemsPlaced);
表达式countsell=builder.count(itemsSold);
标准查询
.select(builder.tuple(root、countPlaced.alias(“itemsPlaced”)、countsell.alias(“itemsSold”);
if(filters.containsKey(“全名”))
{
where(getOrPredicate(filters、builder、root));
}
where(getAndPredicate(filters、builder、root、itemsPlaced));
List orderList=newarraylist();
if(sortField!=null)
{
orderList.add(sortOrder.equals(升序.value())?builder.asc(root.get(sortField))
:builder.desc(root.get(sortField));
}否则
{
add(builder.asc(root.get(“id”));
}
orderList.add(builder.desc(countplace));
groupBy(root.get(“id”);
列表结果=em.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize)
.getResultList();
列表帐户=新的ArrayList();
for(元组:结果)
{
AccountDTO res=新AccountDTO();
尝试
{
res=ReflectionUtil.copy(AccountDTO.class,tuple.get(0));
}捕获(例外e)
{
e、 printStackTrace();
}
res.setItemsPlaced((长)tuple.get(1));
res.setItemsSold((长)tuple.get(2));
账户添加(res);
}
返回账户;
}

但是,当我执行该方法时,会出现以下异常:

javax.servlet.ServletException:org.hibernate.hql.internal.ast.QuerySyntaxException:with子句引用了两个不同于子句的元素[从com.persistence.entities.Account中选择generatedAlias0、count(generatedAlias1)、count(generatedAlias2)作为generatedAlias0左连接generatedAlias0.items作为generatedAlias1和(generatedAlias1.status=:param0)和(generatedAlias1.creator.id=generatedAlias0.id)将generatedAlias0.items作为generatedAlias2与(1=1)和(generatedAlias1.status=:param1)左连接,其中1=1按generatedAlias0.id分组]

我不明白为什么join.on方法不起作用,以及keywork“with”出现的位置。我也尝试了很多例子,也许我的配置是错误的

My persistence.xml:

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
    version="2.1">
    <persistence-unit name="persistence" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/postgresDS</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <properties>
            <property name="openjpa.TransactionMode" value="managed" />
            <property name="openjpa.ConnectionFactoryMode" value="managed" />
            <property name="openjpa.jdbc.DBDictionary" value="db2" />
            <property name="openjpa.DataCache" value="true" />
            <property name="openjpa.Log"
                value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

java:jboss/datasources/postgresd
假的
启用\u选择性

itemsold
itemsPlaced
在同一个属性
items
上连接。这是有意的吗?是的,我想计算不同类型的项目,有多少项目处于关闭状态,有多少项目处于打开状态我对JPA来说有点陌生,但我希望join.on函数添加一个“on”关键字to我的查询,这将是生成的sql中唯一的问题,为什么要添加关键字“with”?
itemsSold
itemsPlaced
在同一个属性
items
上连接。是否打算这样做?是的,我想计算不同类型的项目,有多少项目的帐户处于关闭状态,有多少项目处于状态s openedI对JPA来说是个新手,但我希望函数join.on会在我的查询中添加一个“on”关键字,这将是生成的sql中唯一的问题,为什么会添加关键字“with”?