Spring Boot JpaRepository 保存调用似乎没有做任何事情

Posted

技术标签:

【中文标题】Spring Boot JpaRepository 保存调用似乎没有做任何事情【英文标题】:Spring Boot JpaRepository save call doesn't seem to be doing anything 【发布时间】:2018-10-04 02:03:55 【问题描述】:

我正在编写一个使用 JpaRepository 接口的 Spring Boot 应用程序。在我尝试编写一些对象的服务方法中,对两个存储库的 save() 方法的调用似乎没有做任何事情,但也没有抛出任何异常。

我正在使用带有 ISAM 表和 mysql5Dialect 的 mysql。

这是我的实体: 预订

package com.bigbadcon.dataservices.entity.eventManager;

import com.bigbadcon.dataservices.entity.wordpress.Users;

import javax.persistence.*;
import java.math.BigDecimal;
import java.sql.Timestamp;


@Entity
@Table(name = "bookings", schema = "redacted", catalog = "")
public class Bookings 
    private Long bookingId;
    private Integer bookingSpaces;
    private String bookingComment;
    private Timestamp bookingDate;
    private Integer bookingStatus;
    private BigDecimal bookingPrice;
    private String bookingMeta;
    private BigDecimal bookingTaxRate;
    private BigDecimal bookingTaxes;

    private Users user;
    private Events event;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "booking_id")
    public Long getBookingId() 
        return bookingId;
    

    public void setBookingId(Long bookingId) 
        this.bookingId = bookingId;
    

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "person_id", referencedColumnName = "ID")
    public Users getUser() 
        return this.user;
    

    public void setUser(Users user) 
        this.user = user;
    

    @ManyToOne
    @JoinColumn(name = "event_id")
    public Events getEvent() 
        return this.event;
    

    public void setEvent(Events event) 
        this.event = event;
    


    @Basic
    @Column(name = "booking_spaces")
    public Integer getBookingSpaces() 
        return bookingSpaces;
    

    public void setBookingSpaces(Integer bookingSpaces) 
        this.bookingSpaces = bookingSpaces;
    

    @Basic
    @Column(name = "booking_comment", columnDefinition = "TEXT")
    public String getBookingComment() 
        return bookingComment;
    

    public void setBookingComment(String bookingComment) 
        this.bookingComment = bookingComment;
    

    @Basic
    @Column(name = "booking_date")
    public Timestamp getBookingDate() 
        return bookingDate;
    

    public void setBookingDate(Timestamp bookingDate) 
        this.bookingDate = bookingDate;
    

    @Basic
    @Column(name = "booking_status", columnDefinition = "TINYINT", length = 1)
    public Integer getBookingStatus() 
        return bookingStatus;
    

    public void setBookingStatus(Integer bookingStatus) 
        this.bookingStatus = bookingStatus;
    

    @Basic
    @Column(name = "booking_price")
    public BigDecimal getBookingPrice() 
        return bookingPrice;
    

    public void setBookingPrice(BigDecimal bookingPrice) 
        this.bookingPrice = bookingPrice;
    

    @Basic
    @Lob
    @Column(name = "booking_meta")
    public String getBookingMeta() 
        return bookingMeta;
    

    public void setBookingMeta(String bookingMeta) 
        this.bookingMeta = bookingMeta;
    

    @Basic
    @Column(name = "booking_tax_rate")
    public BigDecimal getBookingTaxRate() 
        return bookingTaxRate;
    

    public void setBookingTaxRate(BigDecimal bookingTaxRate) 
        this.bookingTaxRate = bookingTaxRate;
    

    @Basic
    @Column(name = "booking_taxes")
    public BigDecimal getBookingTaxes() 
        return bookingTaxes;
    

    public void setBookingTaxes(BigDecimal bookingTaxes) 
        this.bookingTaxes = bookingTaxes;
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Bookings that = (Bookings) o;

        if (bookingId != null ? !bookingId.equals(that.bookingId) : that.bookingId != null) return false;
        if (bookingSpaces != null ? !bookingSpaces.equals(that.bookingSpaces) : that.bookingSpaces != null)
            return false;
        if (bookingComment != null ? !bookingComment.equals(that.bookingComment) : that.bookingComment != null)
            return false;
        if (bookingDate != null ? !bookingDate.equals(that.bookingDate) : that.bookingDate != null) return false;
        if (bookingStatus != null ? !bookingStatus.equals(that.bookingStatus) : that.bookingStatus != null)
            return false;
        if (bookingPrice != null ? !bookingPrice.equals(that.bookingPrice) : that.bookingPrice != null) return false;
        if (bookingMeta != null ? !bookingMeta.equals(that.bookingMeta) : that.bookingMeta != null) return false;
        if (bookingTaxRate != null ? !bookingTaxRate.equals(that.bookingTaxRate) : that.bookingTaxRate != null)
            return false;
        if (bookingTaxes != null ? !bookingTaxes.equals(that.bookingTaxes) : that.bookingTaxes != null) return false;

        return true;
    

    @Override
    public int hashCode() 
        int result = bookingId != null ? bookingId.hashCode() : 0;
        result = 31 * result + (bookingSpaces != null ? bookingSpaces.hashCode() : 0);
        result = 31 * result + (bookingComment != null ? bookingComment.hashCode() : 0);
        result = 31 * result + (bookingDate != null ? bookingDate.hashCode() : 0);
        result = 31 * result + (bookingStatus != null ? bookingStatus.hashCode() : 0);
        result = 31 * result + (bookingPrice != null ? bookingPrice.hashCode() : 0);
        result = 31 * result + (bookingMeta != null ? bookingMeta.hashCode() : 0);
        result = 31 * result + (bookingTaxRate != null ? bookingTaxRate.hashCode() : 0);
        result = 31 * result + (bookingTaxes != null ? bookingTaxes.hashCode() : 0);
        return result;
    

门票预订

import com.bigbadcon.dataservices.entity.wordpress.Users;

import javax.persistence.*;
import java.math.BigDecimal;
import java.sql.Timestamp;

@Entity
@Table(name = "bookings", schema = "redacted", catalog = "")
public class Bookings 
    private Long bookingId;
    private Integer bookingSpaces;
    private String bookingComment;
    private Timestamp bookingDate;
    private Integer bookingStatus;
    private BigDecimal bookingPrice;
    private String bookingMeta;
    private BigDecimal bookingTaxRate;
    private BigDecimal bookingTaxes;

    private Users user;
    private Events event;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "booking_id")
    public Long getBookingId() 
        return bookingId;
    

    public void setBookingId(Long bookingId) 
        this.bookingId = bookingId;
    

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "person_id", referencedColumnName = "ID")
    public Users getUser() 
        return this.user;
    

    public void setUser(Users user) 
        this.user = user;
    

    @ManyToOne
    @JoinColumn(name = "event_id")
    public Events getEvent() 
        return this.event;
    

    public void setEvent(Events event) 
        this.event = event;
    


    @Basic
    @Column(name = "booking_spaces")
    public Integer getBookingSpaces() 
        return bookingSpaces;
    

    public void setBookingSpaces(Integer bookingSpaces) 
        this.bookingSpaces = bookingSpaces;
    

    @Basic
    @Column(name = "booking_comment", columnDefinition = "TEXT")
    public String getBookingComment() 
        return bookingComment;
    

    public void setBookingComment(String bookingComment) 
        this.bookingComment = bookingComment;
    

    @Basic
    @Column(name = "booking_date")
    public Timestamp getBookingDate() 
        return bookingDate;
    

    public void setBookingDate(Timestamp bookingDate) 
        this.bookingDate = bookingDate;
    

    @Basic
    @Column(name = "booking_status", columnDefinition = "TINYINT", length = 1)
    public Integer getBookingStatus() 
        return bookingStatus;
    

    public void setBookingStatus(Integer bookingStatus) 
        this.bookingStatus = bookingStatus;
    

    @Basic
    @Column(name = "booking_price")
    public BigDecimal getBookingPrice() 
        return bookingPrice;
    

    public void setBookingPrice(BigDecimal bookingPrice) 
        this.bookingPrice = bookingPrice;
    

    @Basic
    @Lob
    @Column(name = "booking_meta")
    public String getBookingMeta() 
        return bookingMeta;
    

    public void setBookingMeta(String bookingMeta) 
        this.bookingMeta = bookingMeta;
    

    @Basic
    @Column(name = "booking_tax_rate")
    public BigDecimal getBookingTaxRate() 
        return bookingTaxRate;
    

    public void setBookingTaxRate(BigDecimal bookingTaxRate) 
        this.bookingTaxRate = bookingTaxRate;
    

    @Basic
    @Column(name = "booking_taxes")
    public BigDecimal getBookingTaxes() 
        return bookingTaxes;
    

    public void setBookingTaxes(BigDecimal bookingTaxes) 
        this.bookingTaxes = bookingTaxes;
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Bookings that = (Bookings) o;

        if (bookingId != null ? !bookingId.equals(that.bookingId) : that.bookingId != null) return false;
        if (bookingSpaces != null ? !bookingSpaces.equals(that.bookingSpaces) : that.bookingSpaces != null)
            return false;
        if (bookingComment != null ? !bookingComment.equals(that.bookingComment) : that.bookingComment != null)
            return false;
        if (bookingDate != null ? !bookingDate.equals(that.bookingDate) : that.bookingDate != null) return false;
        if (bookingStatus != null ? !bookingStatus.equals(that.bookingStatus) : that.bookingStatus != null)
            return false;
        if (bookingPrice != null ? !bookingPrice.equals(that.bookingPrice) : that.bookingPrice != null) return false;
        if (bookingMeta != null ? !bookingMeta.equals(that.bookingMeta) : that.bookingMeta != null) return false;
        if (bookingTaxRate != null ? !bookingTaxRate.equals(that.bookingTaxRate) : that.bookingTaxRate != null)
            return false;
        if (bookingTaxes != null ? !bookingTaxes.equals(that.bookingTaxes) : that.bookingTaxes != null) return false;

        return true;
    

    @Override
    public int hashCode() 
        int result = bookingId != null ? bookingId.hashCode() : 0;
        result = 31 * result + (bookingSpaces != null ? bookingSpaces.hashCode() : 0);
        result = 31 * result + (bookingComment != null ? bookingComment.hashCode() : 0);
        result = 31 * result + (bookingDate != null ? bookingDate.hashCode() : 0);
        result = 31 * result + (bookingStatus != null ? bookingStatus.hashCode() : 0);
        result = 31 * result + (bookingPrice != null ? bookingPrice.hashCode() : 0);
        result = 31 * result + (bookingMeta != null ? bookingMeta.hashCode() : 0);
        result = 31 * result + (bookingTaxRate != null ? bookingTaxRate.hashCode() : 0);
        result = 31 * result + (bookingTaxes != null ? bookingTaxes.hashCode() : 0);
        return result;
    

这里是 Bookings 实体的 JpaRepository:

import com.bigbadcon.dataservices.entity.eventManager.Bookings;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Repository
@Transactional
public interface BookingsRepositoryInterface extends JpaRepository<Bookings, Long> 

    @Query(value = "SELECT b from Bookings b where b.user.id = ?1 AND b.event.eventName not like 'Verify % badge%' " +
            "AND FUNCTION('YEAR', b.event.eventStartDate) = ?2 and b.bookingStatus = 1")
    List<Bookings> findForUser(Long userId, Integer filterYear);

    @Query(value = "SELECT b from Bookings b where b.event.eventId= ?1 and b.bookingSpaces = 1 and b.bookingStatus = 1")
    List<Bookings> findForEvent(Long eventId);


对于 TicketsBookings 实体:

package com.bigbadcon.dataservices.repository.eventManager.interfaces;

import com.bigbadcon.dataservices.entity.eventManager.TicketsBookings;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Repository
@Transactional
public interface TicketsBookingsRepositoryInterface extends JpaRepository<TicketsBookings, Long> 

    @Query(value = "SELECT tb from TicketsBookings tb where tb.bookingId.event.eventId = ?1 ")
    List<TicketsBookings> findForEvent(Long eventId);

最后,这是不正常的方法:

@Service
public class BookingsService 


    @Autowired
    private BookingsRepositoryInterface bookingsDAO;

    @Autowired
    private TicketsRepositoryInterface ticketsDAO;

    @Autowired
    private TicketsBookingsRepositoryInterface ticketsBookingsDAO;

    @Autowired
    private EventsRepositoryInterface eventsDAO;

    @Autowired
    private UsersRepositoryInterface usersDAO;

    @Autowired
    private OptionsRepositoryInterface optionsDAO;

    @Autowired
    private EmailService emailService;

    @Autowired
    private BookingsService bookingsService;

    @Autowired
    private SecurityService securityService;

    @PersistenceContext
    EntityManager em;

    private static final Logger log = LoggerFactory.getLogger(BookingsService.class);

    public HashMap<String, Boolean> stateTable;

    private Integer statusBooked = 1;
    private Integer statusCancelled = 2;
    private Integer statusDeleted = 3;

    /**
     * <p>This method is only to be called by the game registration consumer. It assumes the UI has done some sort
     * of check that the user isn't already booked in the game. The WP UI does this.</p>
     * <p>Admin users can call the addPlayerToGame method instead.</p>
     * @param eventId
     * @param userId
     * @param uuid
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createBooking(Long eventId, Long userId, String uuid) 

        Events event = eventsDAO.findOne(eventId);
        log.info("Event found: " + event.toString());
        Users user = usersDAO.findOne(userId);
        log.info("User found: " + user.toString());

        Timestamp now = new Timestamp(System.currentTimeMillis());

        Tickets ticket = ticketsDAO.findTicketByEventId(event.getEventId());
        if (ticket == null) 
            log.info("Event " + event.getEventId() + " is not open for registration yet.");
            return;
        
        log.info("Found ticket: " + ticket.toString());

        List<Bookings> bookingsList = bookingsDAO.findForEvent(event.getEventId());
        for (Bookings booking : bookingsList) 
            if (booking.getUser().getId().equals(userId)) 
                log.info("User " + booking.getUser().getDisplayName() + " has already signed up for event id " + event.getEventId());
                return;
            
        

        Integer bookingSpaces = 1;
        Integer bookingStatus = 1;
        if (bookingsList.size() >= ticket.getTicketSpaces()) 
            bookingSpaces = 0;
            bookingStatus = 4;
        

        Bookings booking = new Bookings();
        booking.setEvent(event);
        booking.setUser(user);
        booking.setBookingSpaces(bookingSpaces);
        booking.setBookingDate(now);
        booking.setBookingStatus(bookingStatus);
        booking.setBookingMeta("a:0:");
        bookingsDAO.save(booking);

        TicketsBookings ticketBooking = new TicketsBookings();
        ticketBooking.setBookingId(booking);
        ticketBooking.setTicketId(ticket.getTicketId());
        ticketBooking.setTicketBookingSpaces(statusBooked);
        ticketBooking.setTicketBookingPrice(new BigDecimal(0));
        ticketsBookingsDAO.save(ticketBooking);


        //TODO send rejection mail for overbookings
        try 
            if (bookingStatus.equals(1)) 
                emailService.sendEmail(createConfirmedPlayerEmail(user, event));
                emailService.sendEmail(createConfirmedHostEmail(user, event));
                bookingsService.stateTable.put(uuid, new Boolean(true));
            
            else 
                bookingsService.stateTable.put(uuid, new Boolean(false));
            
        
        catch (Exception e) 
            e.printStackTrace();
        

    

根据我在该主题上阅读的内容,使用 @Transactional 注释的方法应在方法返回后提交。当我执行该方法时,它实际上会打印到它正在保存的日志中。但是我打开了sql调试,保存的时候不打印任何sql语句。 (它会在选择时打印 sql 语句。)

该方法在进行上述选择时没有问题,只有后半部分的保存。不会引发异常,但数据不会出现在实体正在使用的表中。每次保存的日志中打印的唯一行如下所示:

o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]

我不确定这是否相关,但此调用是由侦听器类为 jms 队列进行的。

我的问题是,我是否遗漏了以这种方式启用持久数据的任何东西?根据我的阅读,@Transactional 自动将 readOnly 设置为 true,并且我的 IDE 确认了这一点。我错过了什么重要的事情吗?

【问题讨论】:

只是我的两分钱,MyISAM 不是事务性的,请参阅:***.com/questions/8036005/…,也许你应该尝试一下 InnoDB 可能与问题无关,但@Transactional 属于服务而非存储库。 我不敢相信我忘记了 MyISAM 不是事务性的。 磕头 我修改了所有表以使用 InnoDB,并从所有存储库接口中删除了 @Transactional 注释,并将属性文件中的方言更改为 MySQL5InnoDBDialect。行为没有变化。 您确认方法执行确实到达了保存部分吗?因为在所有这些预订和机票保存之前,有几个 ifs 最终会返回 【参考方案1】:

对于以后阅读本文的任何人,问题的根本原因是服务方法调用来自消息队列接收器类。我不确定为什么。当我将调用直接移动到 Web 服务而不是队列接收器时,插入没有问题。

【讨论】:

以上是关于Spring Boot JpaRepository 保存调用似乎没有做任何事情的主要内容,如果未能解决你的问题,请参考以下文章

使用 jparepository 调用存储过程 Spring Boot 应用程序

Spring Boot + JPA 多模块项目无法注入 JpaRepository 接口

Spring Boot JpaRepository 保存调用似乎没有做任何事情

如何在 JpaRepository spring boot 中使用 postgresql array_agg 函数?

Spring Boot 应用程序。批处理在 JpaRepository.saveAll 方法中不起作用

spring boot 学习心得 使用JpaRepository注解自定义SQL查询数据库多表查询