#java #sql #spring #hibernate #jpql
#java #sql #весна #спящий режим #jpql
Вопрос:
В основном я пытаюсь выполнить запрос и поместить результат в объект класса Account
. Что очень важно подчеркнуть, так это то, что запрос выполняет СОЕДИНЕНИЕ между 2 таблицами, КОТОРЫЕ НЕ ОТОБРАЖАЮТСЯ как @Entity
. Итак, как я могу это сделать?
Это мой FooRepository.java класс
@Repository
public interface FooRepository extends JpaRepository<Foo, Long> {
Foo findById(Long id);
@Query(value = "SELECT Q1.ACCOUNT_NAME,"
"Q2.GROUP_NAME "
"FROM USERS_DEV Q1n"
"JOIN USERS_GROUPS Q2 ON Q1.ACCOUNT_NAME = Q2.ACCOUNT_NAMEn"
"WHERE LOWER(Q1.ACCOUNT_NAME) = 'john.pit'", nativeQuery = true)
List<Account> getAllAccounts();
Итак, как я могу изменить свой запрос, чтобы получить желаемый результат?
И вот моя учетная запись.класс java
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;
}
}
Комментарии:
1. Избегайте использования
nativeQuery
, когда это возможно. Тем не менее, это должно сработать, если вы соответствующим образом сопоставите имена свойств (постоянный регистр больше не используется по умолчанию).
Ответ №1:
Вы можете использовать EntityManager
и ResultTransformer
:
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();
Может потребоваться приведение.
Комментарии:
1. Я сделал, как вы сказали, так что теперь я получаю это: InvalidDataAccessResourceUsageException: не удалось извлечь результирующий набор; SQL [n / a]; вложенным исключением является org.hibernate.exception. SQLGrammarException: не удалось извлечь результирующий набор, вызванный: java.sql.SQLSyntaxErrorException: ORA-00923: ключевое слово FROM не найдено там, где ожидалось
2. @MariusPop да, это моя ошибка, я думал, что это jpql. Для native должно быть другое решение, позвольте мне отредактировать свой ответ
3. @MariusPop попробуйте сейчас. Не беспокойтесь о том, что его устаревание
ResultTransformer
не будет удалено, пока не будет достойной замены4. я не совсем знаком с EntityManager. Куда точнее я должен вставить этот код? Все еще в классе репозитория? Должен ли я создать экземпляр EntityManager?
5. @MariusPop Я предлагаю создать отдельный класс
CustomFooRepository
, там вы можете создать метод, который возвращаетList<Account>
и вставляет код.EntityManager
может быть введен с помощью@Autowired
Ответ №2:
Может быть, я ошибаюсь, но я помню, что вы можете выполнить следующее (с помощью HQL):
@Query("select new Account(u.name, g.groupName) "
"from User as u"
"join u.group as g"
"where LOWER(u.name) = 'john.pit'")
Синтаксис может быть неправильным, но я уверен, что вы можете использовать конструктор DTO в инструкции select, если используете HQL.
Надеюсь, это поможет вам: D
Комментарии:
1. это работает, только если таблицы отображаются как объекты
Ответ №3:
В качестве альтернативы вы можете использовать @NamedNativeQuery
with @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();
}
Дополнительные сведения см. в документации по гибернации.
Комментарии:
1. Не удалось извлечь результирующий набор, вызванный: java.sql.SQLSyntaxErrorException: ORA-00923: ключевое слово FROM не найдено там, где ожидалось
2. все еще получаю
FROM keyword not found where expected
, но когда я копирую-вставляю запрос в sql developer, он работает отлично. Я действительно не понимаю: (3. @MariusPop Попробуйте использовать сопоставление из моего обновленного ответа. Если это не поможет, пожалуйста
hibernate.show_sql
, включитеhibernate.format_sql
hibernate.use_sql_comments
и посмотрите, какой именно запрос выполнен.4. проблема заключалась в интервале. Я не знал, что sql склеивает все, поэтому некоторые слова также были склеены
5. Хорошо, да, я видел ваш вопрос по этому поводу.