我正在使用Spring Boot开发REST API,它将用于管理物品拍卖。
参加拍卖的用户将在单独的用户表
中要拍卖的物品将在 Auction_items表中,以及拍卖的开始和结束时间,如果拍卖仍在进行中,则获胜者为空。
用户为各个项目完成的所有出价都在出价表
中我已经尝试了不同的方式(cron,fixedRate,fixedDelay)来计划任务,所有这些都遇到了类似的错误,我怀疑可能是由于发生数据库问题。 / strong>
下面是表和相应的模型类以及服务和存储库接口。
用户表:
CREATE TABLE USERS
(
USER_ID SERIAL,
NAME VARCHAR(200),
EMAIL VARCHAR(200),
PASSWORD VARCHAR(200),
PRIMARY KEY(USER_ID)
);
AUCTION_ITEMS表:
CREATE TABLE AUCTION_ITEMS
(
ITEM_ID SERIAL,
ITEM_NAME VARCHAR(200),
ITEM_DESCRIPTION TEXT,
START_TIME TIMESTAMP,
END_TIME TIMESTAMP,
STARTING_AMOUNT INT,
WINNER INT,
PRIMARY KEY(ITEM_ID),
FOREIGN KEY(WINNER) REFERENCES USERS(USER_ID) ON DELETE CASCADE
);
出价表:
CREATE TABLE BIDS
(
BID_ID SERIAL,
ITEM_ID INT,
USER_ID INT,
AMOUNT INT,
PRIMARY KEY(BID_ID),
FOREIGN KEY(ITEM_ID) REFERENCES AUCTION_ITEMS(ITEM_ID) ON DELETE
CASCADE,
FOREIGN KEY(USER_ID) REFERENCES USERS(USER_ID) ON DELETE CASCADE
);
以下是上表的模型类:
User.java:
@Entity
@Table(name="USERS")
public class User {
@Id
private Integer user_id;
private String name;
private String email;
private String password;
//getter setter methods
}
Item.java:
@Entity
@Table(name="AUCTION_ITEMS")
public class Item {
@Id
private Integer item_id;
private String item_name;
private String item_description;
private Timestamp start_time;
private Timestamp end_time;
private int starting_amount;
@ManyToOne
@JoinColumn(name="winner")
private User user;
//getter setter methods
}
Bid.java:
@Entity
@Table(name="BIDS")
public class Bid {
@Id
private Integer bid_id;
@ManyToOne
@JoinColumn(name="item_id")
private Item item;
@ManyToOne
@JoinColumn(name="user_id")
private User user;
private int amount;
//getter setter nethods
}
下面是服务类,其中我定义了 scheduledTask()方法,以便在经过拍卖品的结束时间后运行并计算拍卖品的赢家:
ItemService.java:
@Service
public class ItemService {
@Autowired
private ItemRepository itemRepository;
@Autowired
private UserRepository userRepository;
public List<Item> getAllItems(){
return (List<Item>) itemRepository.findAll();
}
public Object getItem(Integer id) {
Item i = itemRepository.findById(id).orElse(null);
if(i.getUser()!=null) {
return i.getUser();
}
else {
//will be returning highest bid amount for that particular item
return itemRepository.getMaxBid(id);
}
}
@Scheduled(cron="20 36 17 * * ?")
public void scheduledTask() {
List<Item> listOfItems = (List<Item>)itemRepository.findAll();
System.out.println("going to update DB");
for(Item i : listOfItems) {
Timestamp time = new Timestamp(System.currentTimeMillis());
if(time.equals(i.getEnd_time()) || time.after(i.getEnd_time())) {
if(i.getUser() == null) {
Integer item_id = i.getItem_id();
Integer winner_id = itemRepository.findWinner(item_id);
User u= userRepository.findById(winner_id).orElse(null);
i.setUser(u);
System.out.println("updated");
}
}
}
}
}
ItemRepository.java:
public interface ItemRepository extends CrudRepository<Item,Integer>{
@Query(value="select max(b.amount) from bids as b where b.item_id=?1",
nativeQuery=true )
public Integer getMaxBid(Integer item_id);
@Query(value="select b.user_id from bids as b where b.item_id=?1 AND
b.amount = (select max(amount) from bids);", nativeQuery=true)
public Integer findWinner(Integer id);
下面是我得到的错误,是时候更新表中的数据了:
2019-04-22 12:55:30.123 INFO 9100 --- [调度-1]> o.h.h.i.QueryTranslatorFactoryInitiator:HHH000397:使用> ASTQueryTranslatorFactory 要更新数据库 2019-04-22 12:55:30.464错误9100 --- [schedule-1]?> o.s.s.s.TaskUtils $ LoggingErrorHandler:>计划任务发生意外错误。
org.springframework.dao.InvalidDataAccessApiUsageException:> org.hibernate.QueryException:JPA样式的位置参数不是整数>常规;嵌套异常是java.lang.IllegalArgumentException:> org.hibernate.QueryException:JPA样式的位置参数不是整数> ordinal 在> org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExcepti> onIfPossible(EntityManagerFactoryUtils.java:373)〜[spring-orm-> 5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPo> ssible(HibernateJpaDialect.java:255)〜[spring-orm->]> 5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExcepti> onIfPossible(AbstractEntityManagerFactoryBean.java:527)〜[spring-orm-> 5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.dao.support.ChainedPersistenceExceptionTranslator.transla> teExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)〜 [spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAcce> ssUtils.java:242)〜[spring-tx-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.in> voke(PersistenceExceptionTranslationInterceptor.java:153)〜[spring-tx-> 5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflecti> veMethodInvocation.java:186)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcess>或$ CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPos> tProcessor.java:138)〜[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6。发布] 在> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflecti> veMethodInvocation.java:186)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(Expose> InvocationInterceptor.java:93)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflecti> veMethodInvocation.java:186)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.data.repository.core.support.SurroundingTransactionDetect> orMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.ja> va:61)〜[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE] 在> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflecti> veMethodInvocation.java:186)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProx> y.java:212)〜[spring-aop-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在com.sun.proxy。$ Proxy91.findUser(未知来源)〜[na:na] at auction.demo.service.ItemService.scheduledTask(ItemService.java:55)>〜[classes /:na] 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)〜 [na:1.8.0_121] 在> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)>〜[na:1.8.0_121] 在> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl。> java:43)〜[na:1.8.0_121] 在java.lang.reflect.Method.invoke(Method.java:498)〜[na:1.8.0_121] 在> org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledM> ethodRunnable.java:84)〜[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(De> legatingErrorHandlingRunnable.java:54)〜[spring-context-> 5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> org.springframework.scheduling.concurrent.ReschedulingRunnable.run(Rescheduli> ngRunnable.java:93)[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE] 在> java.util.concurrent.Executors $ RunnableAdapter.call(Executors.java:511) [na:1.8.0_121] 在java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121] 在> java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.access $ 2> 01(ScheduledThreadPoolExecutor.java:180)[na:1.8.0_121] 在> java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.run(Sche> duledThreadPoolExecutor.java:293)[na:1.8.0_121] 在> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:114> 2)[na:1.8.0_121] 在> java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:61> 7)[na:1.8.0_121] 在java.lang.Thread.run(Thread.java:745)[na:1.8.0_121]
问题:创建一个计划任务,该任务在某项物品的拍卖结束时运行,并从Bids表中确定该项目的胜者,并将该用户的ID存储在Auction_items表的Winner列中
我认为上述错误背后的原因是,我在模型类中创建了一个User成员变量,但是在表端,它仅期望User的ID而不是完整的User实例。< / p>
即使这是原因,我也不确定如何解决它,如果这不是原因,如果使用setUser设置了正确的用户实例,应用程序会自动将适当的user_id存储在获奖者列中()。
请注意,我已经在类中通过main()方法使用了@EnabledScheduling。
更新:粘贴新的ItemService.java,Item.java 在Item.java中,我已将数据类型User用作成员变量,因为将其设置为Integer不起作用
答案 0 :(得分:1)
ItemRepository
来获取用法不正确的用户实体,则存储库应该管理一种域类型(实体)。findUser
方法,因为存储库已经具有findById
的实现。答案很简短,请创建一个单独的UserRepository
,在其中移动findWinner
方法,然后使用findById
中现有的UserRepository
而不是{ {1}}
答案 1 :(得分:0)
好的,因此,在ItemService.java的ScheduledTask()方法中,控件已遍及每个部分,并且项目实例“ i”也正在更新,我想我只需要使用itemRepository.save(i)将其保存到数据库即可。 下面是scheduleTask()方法的完整实现
@Scheduled(cron="0 17 11 * * ?")
public void scheduledTask() {
List<Item> listOfItems = (List<Item>)itemRepository.findAll();
System.out.println("going to update DB");
for(Item i : listOfItems) {
Timestamp time = new Timestamp(System.currentTimeMillis());
if(time.equals(i.getEnd_time()) || time.after(i.getEnd_time())) {
if(i.getUser() == null) {
Integer item_id = i.getItem_id();
Integer winner_id = itemRepository.findWinner(item_id);
User u= userRepository.findById(winner_id).orElse(null);
i.setUser(u);
itemRepository.save(i);//change in code, which seems to work now
System.out.println("printing item:");
System.out.println(i.getItem_description()+", "+i.getItem_name()+", "+i.getStarting_amount()+", "+i.getItem_id()+", "+i.getEnd_time()+", "+i.getStart_time()+", "+i.getUser().getUser_id());
System.out.println("updated");
}
}
}
}