【问题标题】:Hibernate saveOrUpdate() saves but doesn't updateHibernate saveOrUpdate() 保存但不更新
【发布时间】:2021-07-03 10:34:46
【问题描述】:

我正在学习hibernate和Spring Boot(也是Thymeleaf),遇到了如下问题:

情况:我有一个表单,它根据 GET 方法中的 ID 参数处理创建和更新数据,如果 ID 等于数据库中的一行,则更新,否则保存。 ID 存储在隐藏的输入标签中,并与表单数据一起插入到实体对象中。然后将该对象发送到调用 DAO 以使用 saveOrUpdate() 方法保存或更新数据的服务。

问题总结:在我的服务中,我有一个用 @Transactional 注释的方法,它调用我的 DAO,然后打开一个会话并执行 saveOrUpdate()。问题是这段代码正确地将新数据保存到我的数据库中,但它不会更新现有数据,在日志中 saveOrUpdate() 只选择但不插入。

我尝试了什么:我发现如果我在 DAO 中打开一个新事务,然后提交该事务,一切都会正常工作,但是当我不这样做并且只依赖 @Transactional 注释时上面的服务方法我只能保存新数据但没有更新。

我的带有 Thymeleaf 的 HTML 表单

<form action="#" th:action="@{saveCustomer}" th:object="${newCustomer}" method="post">
            <input type="hidden" th:field="*{id}" />
            <table>
                <tr>
                    <td><label>First Name:</label></td>
                    <td><input type="text" th:field="*{firstName}"/></td>
                </tr>
                <tr>
                    <td><label>Last Name:</label></td>
                    <td><input type="text" th:field="*{lastName}"/></td>
                </tr>
                <tr>
                    <td><label>Email:</label></td>
                    <td><input type="text" th:field="*{email}"/></td>
                </tr>
                <tr>
                    <td><label></label></td>
                    <td><input type="submit" value="Submit" class="save"/></td>
                </tr>
                <tr>
                    <td><label></label></td>
                    <td><input type="reset" value="Reset" class="save"/></td>
                </tr>
            </table>
        </form>

控制器方法

    @PostMapping("/saveCustomer")
    public String saveCustomer(@ModelAttribute("newCustomer") Customer newCustomer) {
        customerService.saveCustomer(newCustomer);
        return "redirect:/list";
    }

服务方式

import javax.transaction.Transactional;

    @Override
    @Transactional
    public void saveCustomer(Customer newCustomer) {
        customerDAO.saveCustomer(newCustomer);
    }

DAO 方法

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Override
    public void saveCustomer(Customer newCustomer) {
        try (Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession()) {
//            If I use transaction like this everything works correctly!
//            Transaction transaction = session.beginTransaction();
            session.saveOrUpdate(newCustomer);
//            transaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

我的客户实体类

import javax.persistence.*;

@Entity
@Table(name = "customer")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

发生这种情况时休眠日志

Hibernate: select customer0_.id as id1_0_, customer0_.email as email2_0_, customer0_.first_name as first_na3_0_, customer0_.last_name as last_nam4_0_ from customer customer0_ order by customer0_.last_name
Hibernate: select customer0_.id as id1_0_0_, customer0_.email as email2_0_0_, customer0_.first_name as first_na3_0_0_, customer0_.last_name as last_nam4_0_0_ from customer customer0_ where customer0_.id=?
Hibernate: select customer0_.id as id1_0_, customer0_.email as email2_0_, customer0_.first_name as first_na3_0_, customer0_.last_name as last_nam4_0_ from customer customer0_ order by customer0_.last_name

我省略了大部分导入以整理代码,因为我只包含了与问题相关的部分对象。

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    您导入了错误的@Transactional 注释。它应该来自包org.springframework.transaction.annotation。这是此注解的 API Doc - https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html

    您还可以使用 Spring Data JPA,并使用 JPA 存储库简化数据库操作,因为它们具有许多易于使用且方便的方法。使用 Spring Data JPA,您只需要创建存储库接口(如下所示),调用它的方法来保存数据:

    @Repository
    public interface CustomerRepository extends JpaRepository<Customer, Integer> {}
    

    在服务中,自动装配此存储库,并调用其保存方法:

    @Autowired
    private CustomerRepository customerRepository;
    
    @org.springframework.transaction.annotation.Transactional
    public Customer saveOrUpdate(Customer customer) {
        return customerRepository.save(customer); // this will save or update (if id is there)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 2023-03-05
      • 2017-04-03
      • 1970-01-01
      • 2021-02-14
      • 2012-07-28
      相关资源
      最近更新 更多