Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring JPA锁定概念_Spring_Jpa_Locking - Fatal编程技术网

Spring JPA锁定概念

Spring JPA锁定概念,spring,jpa,locking,Spring,Jpa,Locking,有人知道如何在SpringJPA中使用带UPDATE语句的锁定,以便一次只能有一个线程更新记录吗 在这里,我试图更新表名aircraft_route的可用性,在更新之前,我想锁定该行,以便其他线程不能同时更新它 错误:非法尝试在本机SQL查询上设置锁定模式 任何帮助都将不胜感激 谢谢 AirCraftRoute.java @Builder @Setter @Getter @AllArgsConstructor @NoArgsConstructor @Entity(name = "aircraft

有人知道如何在SpringJPA中使用带UPDATE语句的锁定,以便一次只能有一个线程更新记录吗

在这里,我试图更新表名aircraft_route的可用性,在更新之前,我想锁定该行,以便其他线程不能同时更新它

错误:非法尝试在本机SQL查询上设置锁定模式

任何帮助都将不胜感激

谢谢

AirCraftRoute.java

@Builder
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity(name = "aircraft_route")
public class AirCraftRoute implements Serializable
{
    @EmbeddedId
    private AirCraftRoutePK pk = new AirCraftRoutePK();

    @ManyToOne
    @MapsId("airCraftId")
    @JoinColumn(name = "aircraft_id")
    private AirCraft airCraft;

    @ManyToOne
    @MapsId("routeId")
    @JoinColumn(name = "route_id")
    private Route route;

    @Column(name = "journey_date")
    private Date journeyDate;

    @Column(name = "departure_time")
    private Time departureTime;

    @Column(name = "arrival_time")
    private Time arrivalTime;

    @Column(name = "fare")
    private float fare;

    @Column(name = "availability")
    private int availability;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof AirCraftRoute)) return false;
        AirCraftRoute that = (AirCraftRoute) o;
        return Float.compare(that.getFare(), getFare()) == 0 &&
                Objects.equals(getAirCraft(), that.getAirCraft()) &&
                Objects.equals(getRoute(), that.getRoute()) &&
                Objects.equals(getJourneyDate(), that.getJourneyDate()) &&
                Objects.equals(getDepartureTime(), that.getDepartureTime()) &&
                Objects.equals(getArrivalTime(), that.getArrivalTime());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getAirCraft(), getRoute(), getJourneyDate(), getDepartureTime(), getArrivalTime(), getFare());
    }
}
@Repository
public interface AirCraftRouteRepository extends JpaRepository<AirCraftRoute,Integer> {

    @Transactional
    @Query(value = "SELECT ar.availability FROM aircraft_route ar WHERE ar.aircraft_id = :airCraftId AND ar.route_id = :routeId FOR UPDATE",nativeQuery = true)
    int getAvailability(@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);

    @Modifying
    @Transactional
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query(value = "UPDATE aircraft_route ar SET ar.availability = ar.availability - :numberOfTickets WHERE ar.aircraft_id = :airCraftId AND ar.route_id = :routeId AND ar.availability > 0",nativeQuery = true)
    int updateAvailability(@Param("numberOfTickets") int numberOfTickets,@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);
}
AirCraftRouteRepository.java

@Builder
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity(name = "aircraft_route")
public class AirCraftRoute implements Serializable
{
    @EmbeddedId
    private AirCraftRoutePK pk = new AirCraftRoutePK();

    @ManyToOne
    @MapsId("airCraftId")
    @JoinColumn(name = "aircraft_id")
    private AirCraft airCraft;

    @ManyToOne
    @MapsId("routeId")
    @JoinColumn(name = "route_id")
    private Route route;

    @Column(name = "journey_date")
    private Date journeyDate;

    @Column(name = "departure_time")
    private Time departureTime;

    @Column(name = "arrival_time")
    private Time arrivalTime;

    @Column(name = "fare")
    private float fare;

    @Column(name = "availability")
    private int availability;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof AirCraftRoute)) return false;
        AirCraftRoute that = (AirCraftRoute) o;
        return Float.compare(that.getFare(), getFare()) == 0 &&
                Objects.equals(getAirCraft(), that.getAirCraft()) &&
                Objects.equals(getRoute(), that.getRoute()) &&
                Objects.equals(getJourneyDate(), that.getJourneyDate()) &&
                Objects.equals(getDepartureTime(), that.getDepartureTime()) &&
                Objects.equals(getArrivalTime(), that.getArrivalTime());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getAirCraft(), getRoute(), getJourneyDate(), getDepartureTime(), getArrivalTime(), getFare());
    }
}
@Repository
public interface AirCraftRouteRepository extends JpaRepository<AirCraftRoute,Integer> {

    @Transactional
    @Query(value = "SELECT ar.availability FROM aircraft_route ar WHERE ar.aircraft_id = :airCraftId AND ar.route_id = :routeId FOR UPDATE",nativeQuery = true)
    int getAvailability(@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);

    @Modifying
    @Transactional
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query(value = "UPDATE aircraft_route ar SET ar.availability = ar.availability - :numberOfTickets WHERE ar.aircraft_id = :airCraftId AND ar.route_id = :routeId AND ar.availability > 0",nativeQuery = true)
    int updateAvailability(@Param("numberOfTickets") int numberOfTickets,@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);
}
@存储库
公共接口AircrafterRouteRepository扩展了JpaRepository{
@交易的
@查询(value=“选择ar.availability FROM aircraft\u route ar,其中ar.aircraft\u id=:aircraft id和ar.route\u id=:routeId进行更新”,nativeQuery=true)
int getAvailability(@Param(“airCraftId”)Long airCraftId,@Param(“routeId”)Long routeId);
@修改
@交易的
@锁(锁模式类型。悲观写入)
@查询(value=“UPDATE aircraft\u route ar SET ar.availability=ar.availability-:numberOfTickets,其中ar.aircraft\u id=:airCraftId和ar.route\u id=:routeId和ar.availability>0”,nativeQuery=true)
int updateAvailability(@Param(“numberOfTickets”)int numberOfTickets、@Param(“airCraftId”)Long airCraftId、@Param(“routeId”)Long routeId);
}

我认为原生SQL根本不需要锁。您可以直接在本机查询中进行更新。像这样

@Transactional
@Query(value = "SELECT * FROM aircraft_route ar WHERE ar.aircraft_id = :airCraftId AND ar.route_id = :routeId FOR UPDATE",nativeQuery = true)
List<Integer> getAvailability(@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);
@Transactional
@查询(value=“选择*自飞机\航路ar,其中ar.aircraft\ id=:airCraftId和ar.route\ id=:routeId进行更新”,nativeQuery=true)
列表getAvailability(@Param(“airCraftId”)Long airCraftId、@Param(“routeId”)Long routeId);

我认为您可以简单地避免使用本机查询来实现这种简单的语法:

@Transactional
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query(value = "SELECT * FROM AircraftRoute ar WHERE ar.id = :airCraftId AND ar.routeId = :routeId")
List<Integer> getAvailability(@Param("airCraftId") Long airCraftId, @Param("routeId") Long routeId);
@Transactional
@锁(锁模式类型。悲观写入)
@查询(value=“选择*自AircraftRoute ar,其中ar.id=:airCraftId和ar.routeId=:routeId”)
列表getAvailability(@Param(“airCraftId”)Long airCraftId、@Param(“routeId”)Long routeId);

用上面的东西。您必须对实体名称和字段使用正确的语法,但是您可以使用
@Lock
Spring注释及其db锁管理,而不是手动处理。

您的解决方案引发异常,原因是“查询公共抽象java.util.List com.abc.gds.repository.AircrafterRouteRepository.getAvailability方法的验证失败”我认为,这是因为:你能发布你的飞机路线实体吗?更新后的接口getAvailability方法呢?知道如何在UPDATE命令中使用“FOR UPDATE”吗@查询(value=“UPDATE aircraft\u route ar SET ar.availability=ar.availability-:numberOfTickets,其中ar.aircraft\u id=:airCraftId和ar.route\u id=:routeId和ar.availability>0”,nativeQuery=true)我们可以在上述命令中使用UPDATE吗?不需要在UPSTATE中使用
。您已经在更新。