2

I'm new to Spring Data and tried to solve the issue by following this post on SO and some other tutorials but without much success.

I'm trying to make a simple Join using Spring Data JPA between 2 tables. The tables in the database are called: * user_vehicle -> contains information about all vehicles per user since 1 user can have many vehicles * vehicle_model which contains data about vehicle models (id, name, etc)

Current data in the database in the user_vehicle table:
ID | vehicle_id | user_id
1 | 1 | 1
2 | 2 | 1

Here is the code I've tried but can't get it to work (getters and setters are removed from the post to shorten it):

@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);
}

I'm expecting to get 2 results in the iterable with filled vehicle_model data. Instead I get 2 results but for the vehicleModels property I get "Unable to evaluate the expression Method threw 'org.hibernate.exception.SQLGrammarException' exception."

Here is the output from the console:

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'

SasaFajkovic
  • 395
  • 1
  • 4
  • 16

2 Answers2

0

Found a solution here: https://www.baeldung.com/jpa-many-to-many

I've been looking it a bit wrong since this is a ManyToMany relationship. My idea was to go to the "middle" table and select all vehicle_id where userId = :id and from the list of vehicle_ids to get details for each vehicle.

Here is the correct implementation that works:

@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;

Finally, in the repository Interface I have a method like this:

public interface UserVehicleRepository extends CrudRepository<UserVehicle, Long> {

Iterable<UserVehicle> findVehicleModelsByUserId(Long userId);

The output comes out like this:

[
    {
        "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
    }
]

The issue is not that I don't really want the user object in the result so now I need to figure that one out. And after that, I will try to map VehicleManufacturer class to get those results as well in the same response.

SasaFajkovic
  • 395
  • 1
  • 4
  • 16
0

Here is the solution to do what I intentionally wanted - to search Vehicles based on the user_id in the user_vehicle table:

@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);

The User class is actually not used at all:

@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;

This is a OneToMany relationship now and is doing what I actually wanted in the first time.

Hope it helps someone

SasaFajkovic
  • 395
  • 1
  • 4
  • 16