如何使用JPA Query更新单个表单

时间:2017-02-25 19:37:46

标签: java spring hibernate jpa spring-data-jpa

我需要帮助。我正在更新我的数据库中的单个字段,但我使用JPA查询不是很好。我还在学习。

@Entity
public class CertificateProgramme {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

        @NotNull(message = "The above field must not be blank.")
        @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\."
                +"[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"
                +"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
                message="Please enter a valid email address")
        private String email;

        private boolean flag;

我想将标志字段更新为false。当我在serviceImpl类中使用save方法时,我能够更新,但是当我在没有保存的情况下尝试它时它不起作用。

我在ServiceImpl中实现的服务接口中定义unFlagger (CertificateProgramme certificateProgramme)方法

public interface CertificateService {
    List<CertificateProgramme> findAll();
    CertificateProgramme ListAll();
    CertificateProgramme findOne(Long id);
    void save(CertificateProgramme certificateProgramme);
    CertificateProgramme flagger(CertificateProgramme certificateProgramme);
    CertificateProgramme unFlagger(CertificateProgramme certificateProgramme);
}

ServiceImpl.java

 @Override
public CertificateProgramme flag(CertificateProgramme certificateProgramme) {
    certificateDao.unFlagger(certificateProgramme);
    return certificateProgramme;
}

Dao.java

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

我需要帮助

@Modifying
@Query("update CertificateProgramme ear set ear.flag = ?#{'FALSE'} where ear.user.id=?#{principal.id}")
CertificateProgramme unFlagger(CertificateProgramme flag);

控制器

这应该更新标志字段但不更新。我宁愿犯错。

@RequestMapping(value = "cert_prog/{certId}", method = RequestMethod.POST)
    public String UpdateFlag(@PathVariable Long certId, CertificateProgramme certificateProgramme){
        certificateService.unFlagger(certificateProgramme);
        return String.format("redirect:/cert_prog/%s/edit", certId);
    }

错误

    2017-02-25 21:40:28.257 ERROR 20769 --- [nio-8080-exec-9] 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.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query] with root cause

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:238) ~[spring-data-jpa-1.9.2.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:78) ~[spring-data-jpa-1.9.2.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:100) ~[spring-data-jpa-1.9.2.RELEASE.jar:na]
    at or

1 个答案:

答案 0 :(得分:1)

你应该修复你的dao方法。如果你想要修改一个不同实体的字段的查询只将那个字段值和实体id传递给方法作为参数(或者甚至只是id,如果你希望你的方法总是将flag设置为false)。然后以适当的JPQL格式在查询中引用它们。可以在spring data JPA documentation

中找到此类案例的示例

在你的情况下它应该是这样的:

<强> CertificateDAO.java

@Modifying
@Query("update CertificateProgramme ear set ear.flag = FALSE where ear.id = ?1")
int unFlagger(Long id);

<强> ServiceImpl.java

@Override
public CertificateProgramme flag(CertificateProgramme certificateProgramme) {
    certificateDao.unFlagger(certificateProgramme.getId());
    return findOne(certificateProgramme.getId());
}

这个应该有效。您可能还可以摆脱将CertificateProgramme传递给服务并仅传递id。