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 函数?