【问题标题】:Unable to create a JOIN using Spring Data JPA无法使用 Spring Data JPA 创建 JOIN
【发布时间】:2019-06-23 00:07:24
【问题描述】:

我是 Spring Data 的新手,并尝试通过遵循 this post on SO 和其他一些教程来解决该问题,但没有取得多大成功。

我正在尝试在 2 个表之间使用 Spring Data JPA 进行简单的联接。 数据库中的表被称为: * user_vehicle -> 包含每个用户所有车辆的信息,因为 1 个用户可以拥有许多车辆 * vehicle_model 包含有关车辆模型的数据(id、名称等)

user_vehicle 表中数据库中的当前数据:
身份证 |车辆编号 |用户ID
1 | 1 | 1
2 | 2 | 1

这是我尝试过但无法正常工作的代码(从帖子中删除了 getter 和 setter 以缩短它):

@Entity(name = "vehicle_model")
public class VehicleModel {

@Id
@Min(1)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long manufacturerId;
private String title;
private int ccm;
private int kw;
private int yearOfManufacture;
private int engineTypeId;
private boolean isActive;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "vehicle_id", insertable = false, updatable = false)
@Fetch(FetchMode.JOIN)
private UserVehicle userVehicle;
}


@Entity(name = "user_vehicle")
public class UserVehicle {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private long vehicleId;
@Column(nullable = false)
private long userId;

@OneToMany(targetEntity = VehicleModel.class, mappedBy = "userVehicle", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<VehicleModel> vehicleModels;
}


@Repository
public interface UserVehicleRepository extends CrudRepository<UserVehicle, Long> 
{
    Iterable<UserVehicle> findVehicleModelsByUserId(Long userId);
}

我希望在具有已填充车辆模型数据的迭代中获得 2 个结果。相反,我得到 2 个结果,但对于 vehicleModels 属性,我得到“无法评估表达式方法抛出 'org.hibernate.exception.SQLGrammarException' 异常。”

这是控制台的输出:

2019-06-23 02:04:10.988 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select uservehicl0_.id as id1_1_, uservehicl0_.user_id as user_id2_1_, uservehicl0_.vehicle_id as vehicle_3_1_ from user_vehicle uservehicl0_ where uservehicl0_.user_id=? 2019-06-23 02:04:11.034 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.035 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.035 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list' 2019-06-23 02:04:11.036 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.037 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.037 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list' 2019-06-23 02:04:11.038 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.039 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.040 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list' 2019-06-23 02:04:11.042 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.043 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.043 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list' 2019-06-23 02:04:11.045 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.046 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.046 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list' 2019-06-23 02:04:11.048 DEBUG 5896 --- [nio-8080-exec-1] org.hibernate.SQL : select vehiclemod0_.vehicle_id as vehicle_9_4_0_, vehiclemod0_.id as id1_4_0_, vehiclemod0_.id as id1_4_1_, vehiclemod0_.ccm as ccm2_4_1_, vehiclemod0_.engine_type_id as engine_t3_4_1_, vehiclemod0_.is_active as is_activ4_4_1_, vehiclemod0_.kw as kw5_4_1_, vehiclemod0_.manufacturer_id as manufact6_4_1_, vehiclemod0_.title as title7_4_1_, vehiclemod0_.vehicle_id as vehicle_9_4_1_, vehiclemod0_.year_of_manufacture as year_of_8_4_1_ from vehicle_model vehiclemod0_ where vehiclemod0_.vehicle_id=? 2019-06-23 02:04:11.049 WARN 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22 2019-06-23 02:04:11.049 ERROR 5896 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'vehiclemod0_.vehicle_id' in 'field list'

【问题讨论】:

  • 你确定你的onetomany映射是正确的吗?因为外键在 user_vehicle 表上。

标签: java jpa spring-data


【解决方案1】:

在这里找到解决方案:https://www.baeldung.com/jpa-many-to-many

我一直在寻找它,因为这是一个多对多关系。我的想法是转到“中间”表并选择 userId = :id 的所有车辆 ID,并从车辆 ID 列表中获取每辆车的详细信息。

下面是正确的实现:

@Entity(name = "user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String firstName;
private String lastName;
private boolean isActive;

@OneToMany(mappedBy = "user")
private Set<UserVehicle> userVehicles;

@Entity(name = "user_vehicle")
public class UserVehicle {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private boolean isActive;

@ManyToOne
@JoinColumn(name = "vehicle_id")
private Vehicle vehicle;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;


@Entity(name = "vehicle_model")
public class Vehicle {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long manufacturerId;
private String title;
private int ccm;
private int kw;
private int yearOfManufacture;
private int engineTypeId;
private boolean isActive;

@OneToMany(mappedBy = "vehicle")
private Set<UserVehicle> userVehicles;

最后,在存储库接口中我有一个这样的方法:

public interface UserVehicleRepository extends CrudRepository<UserVehicle, Long> {

Iterable<UserVehicle> findVehicleModelsByUserId(Long userId);

输出如下:

[
    {
        "id": 2,
        "vehicle": {
            "id": 2,
            "manufacturerId": 1,
            "title": "Fazer FZ1S",
            "ccm": 998,
            "kw": 110,
            "yearOfManufacture": 2008,
            "engineTypeId": 1,
            "active": true
        },
        "user": {
            "id": 2,
            "username": "sfajkovic",
            "password": "33",
            "firstName": "Ivan",
            "lastName": "Fajkovic",
            "active": true
        },
        "active": true
    }
]

问题不在于我真的不希望结果中出现用户对象,所以现在我需要弄清楚这一点。之后,我将尝试映射 VehicleManufacturer 类以在相同的响应中获得这些结果。

【讨论】:

    【解决方案2】:

    这是我有意做的解决方案 - 根据 user_vehicle 表中的 user_id 搜索 Vehicles:

    @Entity(name = "user_vehicle")
    public class UserVehicle {
    
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private long id;
      private boolean isActive;
      private long userId;
    
      @ManyToOne
      @JoinColumn(name = "vehicle_id")
      private Vehicle vehicle;
    
    
    @Entity(name = "vehicle_model")
    public class Vehicle {
    
      @Id
      @Min(1)
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private Long manufacturerId;
      private String title;
      private int ccm;
      private int kw;
      private int yearOfManufacture;
      private int engineTypeId;
      private boolean isActive;
    
      @OneToMany(mappedBy = "vehicle")
      private Set<UserVehicle> userVehicles;
    
    
    @Repository
    public interface UserVehicleRepository extends CrudRepository<UserVehicle, Long> {
    
      Iterable<UserVehicle> findVehicleModelsByUserId(Long userId);
    

    User 类实际上根本没有用到:

    @Entity(name = "user")
    public class User {
    
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
      private String username;
      private String password;
      private String firstName;
      private String lastName;
      private boolean isActive;
    

    现在这是一个 OneToMany 关系,并且第一次做我真正想做的事情。

    希望对某人有所帮助

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 1970-01-01
      • 2016-01-08
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 2018-05-22
      • 2017-09-29
      • 2020-01-28
      相关资源
      最近更新 更多