Raducu Raducu - 3 months ago 7
Java Question

JPA Relationship issue

I'm working on a project, and I encountered a problem with the JPA relationship. I've been advised on another thread to change a couple of things, however, I still can't get it to work properly.

I'm getting an exception and I know where the problem is but not sure how to solve it.

here is the User class:

@Entity
@Table(name = "user")
public class UserModel implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "username", nullable = false)
private String username;

@Column(name = "password", length = 500, nullable = false)
private String password;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Car> cars;

}


here is the Car class:

@Entity
@Table(name = "car")
public class Car implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(length = 11)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "make", nullable = false)
private String make;

@Column(name = "model", nullable = false)
private String model;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "id") //here is where the exception throws (duplicated ID or com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'user_model_id' in 'field list' if I change that to user_model_id.
private UserModel userModel;

}


here is the service impl:

@Component
@Transactional(readOnly = true)
public class CarServiceImpl implements CarService {

@Inject
private CarRepository carRepository;

@Inject
private UserRepository userRepository;

@Override
@Transactional(readOnly = false)
public Car addCar(Long userId, Car car) {
User user = userRepository.findOne(userId);
user.getCars().add(car);

car.setUser(user);
carRepository.save(car);

return car;
}


Any help will be really much appreciated.

Thank you so much

Answer

I think mappedBy needs to point to the field name that owns the relation. In this case this is userModel so it should be

@OneToMany(mappedBy = "userModel", cascade = CascadeType.ALL)

If the relationship is bidirectional, the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship. (from https://www.objectdb.com/api/java/jpa/OneToMany)

Also I think that your @JoinColumn annotation is wrong. It should specify the column used to join the related entity - so it cannot be ID but something like user_id

See https://www.objectdb.com/api/java/jpa/JoinColumn#

Also your ddl is wrong - this piece says that cars and users have the same id - which you do not want - your ddl is missing the actual column for the user foreign key

FOREIGN KEY (id)
    REFERENCES game.user (id)

So if you changed JoinColumn to @JoinColumn(name = "user_id") your ddl for the foreign key must be.

CREATE TABLE game.car (
    id INT(11) NOT NULL AUTO_INCREMENT COMMENT '',
    make VARCHAR(15) NOT NULL COMMENT '',
    model VARCHAR(15) NOT NULL COMMENT '',
    PRIMARY KEY (id)  COMMENT '',
    user_id INT(11),
    CONSTRAINT fk_user
    FOREIGN KEY (user_id)
    REFERENCES game.user (id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
)

If I can add my 2 cents to the mapping - try to avoid bidirectional relations wherever you can.