在 Spring 启动应用程序中检索 JPQL 查询作为 DTO

Retrieve JPQL Query as DTO in Spring boot application

我基本上想做的是 运行 查询并将结果放入 class Account 的对象中。需要强调的非常重要的一点是,查询在未映射为 @Entity 的 2 个表之间执行 JOIN。那我该怎么做呢?

这是我的FooRepository.javaclass

@Repository
public interface FooRepository extends JpaRepository<Foo, Long> {

  Foo findById(Long id);

@Query(value = "SELECT Q1.ACCOUNT_NAME," +
          "Q2.GROUP_NAME  " +
          "FROM USERS_DEV Q1\n" +
          "JOIN USERS_GROUPS Q2 ON Q1.ACCOUNT_NAME = Q2.ACCOUNT_NAME\n" +
          "WHERE LOWER(Q1.ACCOUNT_NAME) = 'john.pit'", nativeQuery = true)
  List<Account> getAllAccounts();

那么如何更改我的查询以获得所需的结果?

这是我的 Account.java class

public class Account {

    String samAccountName;
    String groupName;

    public Account(String accountName, String groupName) {
        this.accountName = accountName;
        this.groupName = groupName;
    }

    public String getAccountName() {
        return accountName;
    }

    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }
}

您可以使用 EntityManagerResultTransformer:

entityManager.createNativeQuery(
    "SELECT Q1.ACCOUNT_NAME," +
    "Q2.GROUP_NAME  " +
    "FROM USERS_DEV Q1 " +
    "JOIN USERS_GROUPS Q2 ON Q1.ACCOUNT_NAME = Q2.ACCOUNT_NAME " +
    "WHERE LOWER(Q1.ACCOUNT_NAME) = 'john.pit'"
)
            .unwrap(NativeQuery.class)
            .setResultTransformer(new ResultTransformer() {
                @Override
                public Object transformTuple(Object[] tuple, String[] aliases) {
                    return new Account(
                        (String) tuple[0],
                        (String) tuple[1]
                    );
                }

                @Override
                public List transformList(List collection) {
                    return collection;
                }

            })
            .getResultList();

可能需要演员表。

作为替代方案,您可以通过以下方式将 @NamedNativeQuery@SqlResultSetMapping 结合使用:

@Entity
@NamedNativeQuery(
  name = "findAllAccounts",
  query = 
     "SELECT " +
     "  Q1.ACCOUNT_NAME AS accountName, " +
     "  Q2.GROUP_NAME AS groupName " +
     "FROM USERS_DEV Q1 " +
     "JOIN USERS_GROUPS Q2 ON Q1.ACCOUNT_NAME = Q2.ACCOUNT_NAME " + 
     "WHERE LOWER(Q1.ACCOUNT_NAME) = 'john.pit'",
  resultSetMapping = "findAllAccountsMapping"
)
@SqlResultSetMapping(
   name = "findAllAccountsMapping",
   classes = @ConstructorResult(
      targetClass = Account.class,
      columns = {
         @ColumnResult(name="accountName"),
         @ColumnResult(name="groupName"),
      }
   )
)
public class Foo {
   // ...
}

FooRepository

@Repository
public interface FooRepository extends JpaRepository<Foo, Long> {

  @Query(name = "findAllAccounts", nativeQuery = true)
  List<Account> getAllAccounts();
}

有关其他详细信息,请参阅休眠 documentation

也许我错了,但我记得您可以执行以下操作(使用 HQL):

@Query("select new Account(u.name, g.groupName) " +
          "from User as u" +
          "join u.group as g" +
          "where LOWER(u.name) = 'john.pit'")

语法可能有误,但我相信如果您使用 HQL,您可以在 select 语句中使用 DTO 构造函数。

希望这对你有帮助:D