web-dev-qa-db-fra.com

Comment utiliser JPA Query pour insérer des données dans la base de données?

J'ai un problème avec ma déclaration préparée mais je ne peux pas savoir où se trouve l'erreur. J'essaie d'insérer un lien URI dans la base de données.

 @Repository
 public interface LoggerDao extends CrudRepository<Logger, Long> {
 @Query("select t from Logger t where t.user.id=?#{principal.id}")
 List<Logger> findAll();

@Modifying
@Query(value = "insert into Logger t (t.redirect, t.user.id) VALUES (:insertLink,?#{principal.id})", nativeQuery = true)
@Transactional
void logURI(@Param("insertLink") String insertLink);

Erreur

    2017-03-11 19:52:59.157  WARN 65154 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 42001, SQLState: 42001
2017-03-11 19:52:59.157 ERROR 65154 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper   : Syntax error in SQL statement "INSERT INTO LOGGER T[*] (T.REDIRECT, T.USER.ID) VALUES (?,?) "; expected "., (, DIRECT, SORTED, DEFAULT, VALUES, SET, (, SELECT, FROM"; SQL statement:
insert into Logger t (t.redirect, t.user.id) VALUES (?,?) [42001-190]
2017-03-11 19:52:59.181 ERROR 65154 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [insert into Logger t (t.redirect, t.user.id) VALUES (?,?)]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement] with root cause

org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "INSERT INTO LOGGER T[*] (T.REDIRECT, T.USER.ID) VALUES (?,?) "; expected "., (, DIRECT, SORTED, DEFAULT, VALUES, SET, (, SELECT, FROM"; SQL statement:
insert into Logger t (t.redirect, t.user.id) VALUES (?,?) [42001-190]
    at org.h2.engine.SessionRemote.done(SessionRemote.Java:624) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.command.CommandRemote.prepare(CommandRemote.Java:68) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.command.CommandRemote.<init>(CommandRemote.Java:45) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.Java:494) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.Java:1188) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.Java:72) ~[h2-1.4.190.jar:1.4.190]
    at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.Java:276) ~[h2-1.4.190.jar:1.4.190]
    at org.Apache.Tomcat
8
Arthur Decker

J'ai réussi à résoudre le problème. J'ai ajouté un identifiant aux paramètres afin que je puisse passer l'identifiant de l'utilisateur, en utilisant Principal dans le contrôleur.

@Repository
public interface LoggerDao extends CrudRepository<Logger, Long> {
    @Query("select t from Logger t where t.user.id=?#{principal.id}")
    List<Logger> findAll();

    @Modifying
    @Query(value = "insert into Logger (redirect,user_id) VALUES (:insertLink,:id)", nativeQuery = true)
    @Transactional
    void logURI(@Param("insertLink") String insertLink, @Param("id") Long id);
7
Arthur Decker

Il y a un moyen de faire des insertions en utilisant des requêtes obj (pas natives) (en utilisant @Query & @Modifying) mais cela dépend de la base de données que vous utilisez. Ci-dessous a fonctionné pour moi dans Oracle (en utilisant Dual table):

@Repository
public interface DualRepository extends JpaRepository<Dual,Long> {
    @Modifying
    @Query("insert into Person (id,name,age) select :id,:name,:age from Dual")
    public int modifyingQueryInsertPerson(@Param("id")Long id, @Param("name")String name, @Param("age")Integer age);
}

Voici un lien qui montre en bas quel support de db sélectionnez stmts sans clause from: http://modern-sql.com/use-case/select-without-from

1
A.P