With the query Select c from Card c join User u on c.userId=u.userId where u.username=':u', I am trying to grab a list of Cards for the User based on the username available in User the table. However, I am running into the antlr.SemanticException: could not resolve property: userId of: com.abc.SheridanSportsWAR.entity.Card exception when I run it. How do I reference the UserId column in my Card entity?
Card.java
#Entity
public class Card {
#Id
#Column(name="CardId")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer cardId;
#Column(name="CardNumber")
private String cardNumber;
#Column(name="CardType")
private String cardType;
#Column(name="ExpiryMonth")
private String expiryMonth;
#Column(name="ExpiryYear")
private String expiryYear;
#Column(name="CardHolder")
private String cardHolder;
#ManyToOne(cascade = {CascadeType.MERGE, CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name = "UserId")
private User userJ;
#OneToMany(mappedBy = "cardJ")
private List<Purchase> purchases;
User.java
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="UserId")
private Integer userId;
#Column(name="FirstName")
private String firstName;
#Column(name="LastName")
private String lastName;
#Column(name="Email")
private String email;
#Column(name="Username")
private String username;
#Column(name="Password")
private String password;
#Column(name="RoleName")
private String roleName;
#OneToMany(mappedBy="userJ", cascade= CascadeType.ALL)
private List<Card> cards;
The error message is pretty clear. There is no field userId in your Card entity. Create one like that:
#Column(name = "UserId", insertable=false, updatable=false)
private Integer userId;
AFAIK, the problem seems to be that there's no userId column in the card table.
Related
New to Hibernate and HQL in general. I have these following entities.
Employee entity
public class Employee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private Integer authority;
#Column
private String username;
#Column(name = "user_password")
private String password;
#Column
private String title;
#OneToOne
#JoinColumn(name = "person_id", referencedColumnName = "id")
private Person person;
#Column
private Integer gender;
#Column
private String ssn;
#Column(name = "car_info")
private String carInfo;
#Column(name = "birth_date")
private Date birthDate; //java.util Date vs java.sql.Date?
#OneToOne
#JoinColumn(name = "visa_status_id", referencedColumnName = "id")
private VisaStatus visaStatus;
#Column(name = "license_number")
private Integer licenseNumber;
#Column(name = "license_expiration_date")
private Date licenseExpirationDate;
#ManyToOne
#JoinColumn(name = "housing_id", referencedColumnName = "id")
private House house;
}
Person entity
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "preferred_name")
private String preferredName;
#ManyToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#Column
private String email;
#Column(name = "ceil_phone")
private String ceilPhone;
#Column(name = "work_phone")
private String workPhone;
}
House entity
public class House implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#ManyToOne
#JoinColumn(name = "contact_id")
private Contact contactHR;
#ManyToOne
#JoinColumn(name = "landlord_id")
private Person landlord;
}
I'm trying to run this HQL:
select person from Employee where house.id=:houseId
I'm basically trying to get all the Person with the houseId from the Employee. Since I'm trying to only get the person, I'm using the select cause.
But I'm getting these errors:
org.hibernate.hql.internal.ast.InvalidPathException: Invalid path: 'house.id'
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'house.id' [select person from example.project.domain.entity.Employee where house.id=:houseId]
I tried the HQL without the select clause and it worked:
from Employee where house.id=:houseId
But I only need person so I didn't want to get everything. Any idea what's wrong?
You asked
Hibernate Invalid Path Exception using HQL
The problem lies on the written query
select person from Employee where house.id=:houseId
Which should contain proper referencing
select p.person from Employee p where p.house.id=:houseId
Why ?
The FROM clause defines which entities the data is going to be selected. Hibernate, or any other JPA implementation, maps the entities to the according database tables and the syntax of a JPQL FROM clause is similar to SQL and indeed uses the entity model for referencing database attributes, which in root query execution (same thing you are doing) one must use the same referencing strategy, which in your case is to use aliases, as A.Panfilov said in comments regardless of hibernate, even in aliasing in SQL is a good practice.
You may find more in here.
I have a User entity with role types Marketer, Managing Director and General Manager . When the UserRole Managing Director logs In, I want the userrole Managing Director to only see customers assigned to Usertype Marketers with the same Branch ID as the Managing Director.
I have a custom Query in the customer repository that returns a null result.
#Query("SELECT customer from Customer customer join customer.marketer marketer "
+ "where marketer.branch = :director")
List<Customer> findByUserBranch(User director);
This is the User entity
#Entity
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String firstName ;
private String lastName;
#Column(name="user_name", unique=true)
private String userName;
private String password;
private String Gender;
private String phoneNumber;
private String email;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#ManyToOne(targetEntity = Branch.class,
fetch = FetchType.LAZY )
#JoinColumn(name="branch_id")
private Branch branch;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createdDate;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<UserRole> userRole = new HashSet<>();
#Enumerated(EnumType.STRING)
private UserStatus status;
#JsonBackReference
#OneToMany(mappedBy="marketer",cascade = CascadeType.ALL, targetEntity=Customer.class)
private List <Customer> customer;
This is the controller class
#GetMapping(value="branch/customers")
public List<Customer> getListByBranch()
{ Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
User loggedInUser = userRepo.findByUserName(authentication.getName()); return customerRepo.findByBranch(loggedInUser);
}
UPDATED :
This is the Customer class
#Entity
#JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class Customer implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8348682056500740593L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String userName;
private String password;
private String firstName ;
private String lastName;
private String gender;
private String Address;
private String maritalStatus;
private String category;
private String motherMaidenName;
private String idType;
private String idNumber;
private String phoneNumber;
private String email;
#Column(nullable = true, length = 64)
private String photos;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dateOfBirth;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date registrationDate;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#ManyToOne(targetEntity = User.class,
fetch = FetchType.LAZY )
#JoinColumn(name="marketer_id")
private User marketer ;
#JsonBackReference
#OneToMany(mappedBy="customer_id",cascade = CascadeType.ALL, targetEntity=Investment.class)
private List<Investment> investment;
I can't make a comment, so i would ask to also give us the customer.class .
Got it resolved . I changed the User object to branch object.
#Query("SELECT customer from Customer customer join "
+ "customer.marketer marketer "
+ "where marketer.branch = :branch")
List<Customer> findByUserBranch(Branch branch);
Then refactored the controller class
#GetMapping(value="branch/customers")
public List<Customer> getListByBranch(Principal principal)
{
User loggedInUser = userRepo.findByUserName(principal.getName());
Branch branchId = loggedInUser.getBranch();
return customerRepo.findByBranch(branchId);
}
I have a many to many mapping: users and rooms, as follow:
User.java
#Entity
#Table(name="users", indexes = {
#Index(unique=true, columnList="uid"),
#Index(unique=true, columnList="backendAccessToken"),
#Index(columnList="backendAccessToken", name="idx_backend")
})
public class User extends BasePersistable {
private static final long serialVersionUID = 1492535311821424305L;
#Column(nullable=false, unique=true)
private String nickname;
#Column(nullable=false)
private Integer uid;
#Column(nullable=false)
private String backendAccessToken;
#Column
private String name;
#Column
#JsonIgnore
private String email;
#Column
private String location;
#Column
private String company;
#Column
private String avatar;
#Column
#JsonIgnore
private String accessToken;
#CreationTimestamp
private Date memberSince;
#ManyToMany(targetEntity=Room.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE })
#JoinTable(name="room_users",
joinColumns={ #JoinColumn(name="user_id") },
inverseJoinColumns={ #JoinColumn(name="room_id") })
private List<Room> rooms = new ArrayList<>();
Room.java
#Entity
#Table(name="rooms", indexes = {
#Index(unique=true, columnList="uid"),
#Index(columnList="uid"),
#Index(columnList="fullName")
})
public class Room extends BasePersistable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(nullable=false)
private Integer uid;
#Column(nullable=false)
private String name;
#Column(nullable=true)
private String fullName;
#Column(nullable=false)
#Lob
private String description;
#Column(nullable=true)
private String homepage;
#Column(nullable=false)
private String owner;
#ManyToOne
private Organization organization;
#OneToMany(mappedBy="room")
#JsonIgnore
private List<Message> messages = new ArrayList<>();
#ManyToMany(mappedBy="rooms", targetEntity=User.class)
#JsonIgnore
private List<User> users = new ArrayList<>();
#Column(name="private")
private Boolean _private = false;
And when I try to create the schema, I'm seeing this error:
A Foreign key refering com.models.Room from com.models.User has the wrong number of column. should be 2
I did some research, tried to use JoinColumns annotation on User and didn't worked.
EDIT
I found the error: the class BasePersistable already defined the id. So I removed the id from Room and it worked. Thanks for the tip Mateusz Korwel and kakashihatake
I'm creating a MySQL database as followed :
database design
the Country and Province tables are pre-filled with data. I have the application running and can get stuff no problem, and also the join table person_has_address works when getting.
however, when I insert data using post I want to be able to set the ID of the province, and let spring data jpa just add that number to add_pro_id in the Address table. For example, when I post the following json:
{ "firstName":"bilbo", "lastName":"baggings", "address":{"street":"streetName", "streetNum":3, "zipcode":"1337GG", "city":"TheCity", "province":{"name":"aProvinceName"}} }
jpa should see that aProvinceName exists and grab that id and add that to add_pro_id.
Now it just insert aProvinceName as new value in province and add the new id to add_pro_id.
The person class:
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="per_id")
private int id;
#Column(name="per_name")
private String firstName;
#Column(name="per_surname")
private String lastName;
#Column(name="per_birth_date")
private String birthDate;
#Column(name="per_fax")
private String fax;
#Column(name="per_phone")
private String phone;
#Column(name="per_email")
private String email;
#OneToOne(optional = false, cascade = CascadeType.ALL)
#JoinTable(name="person_has_address", joinColumns = {#JoinColumn(name="pha_per_id", referencedColumnName = "per_id")}, inverseJoinColumns = {#JoinColumn(name="pha_add_id", referencedColumnName = "add_id")})
private Address address;
// getters and setters
This is the person repository:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
This is the address class:
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="add_id")
private int id;
#Column(name = "add_street")
private String street;
#Column(name="add_street_num")
private int streetNum;
#Column(name="add_zip")
private String zipcode;
#Column(name="add_city")
private String city;
#JoinColumn(name="add_pro_id", referencedColumnName = "pro_id")
#ManyToOne(optional=false, cascade = CascadeType.ALL)
private Province province;
// getters and setters
Province class:
#Entity
public class Province {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="pro_id")
private int id;
#Column(name="pro_name")
private String name;
#ManyToOne
#JoinColumn(name="pro_cou_id")
private Country country;
// getters and setters
And lastly country class:
#Entity
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="cou_id", insertable = false, updatable = false)
private int id;
#Column(name="cou_name", insertable = false, updatable = false)
private String name;
// getters and setters
I've tried adding insertable = false and updatable = false, but the application then just inserts NULL values in my database. I've also tried working with #primarykeyjoins, but to no success.
if anyone knows how I should tackle this problem I would much appreciate it!
Thanks in advance.
Hibernate novice here, running into issues trying to properly map the relationships between my Hibernate Entity classes.
I have a Ticket Entity and a User Entity. A user has many tickets, but a ticket only belongs to one unique user. What i've done is mapped the User - Tickets as a #OneToMany relationship and the Tickets - User as a #ManyToOne relationship. However, I am not getting any tickets returned.
The Query Hibernate is running is:
Hibernate: select tickets0_.user_user_id as user1_1_3_, tickets0_.tickets_ticket_id as tickets2_3_, ticketenti1_.ticket_id as ticket1_0_0_, ticketenti1_.assigned_to_user_id as assigned7_0_0_, ticketenti1_.belongs_to_user_id as belongs8_0_0_, ticketenti1_.date_created as date2_0_0_, ticketenti1_.description as descript3_0_0_, ticketenti1_.status_id as status4_0_0_, ticketenti1_.title as title0_0_, ticketenti1_.urgency_id as urgency6_0_0_, userentity2_.user_id as user1_1_1_, userentity2_.email as email1_1_, userentity2_.firstname as firstname1_1_, userentity2_.lastname as lastname1_1_, userentity2_.password as password1_1_, userentity2_.role_id as role6_1_1_, userentity2_.username as username1_1_, userentity2_.verified as verified1_1_, userentity3_.user_id as user1_1_2_, userentity3_.email as email1_2_, userentity3_.firstname as firstname1_2_, userentity3_.lastname as lastname1_2_, userentity3_.password as password1_2_, userentity3_.role_id as role6_1_2_, userentity3_.username as username1_2_, userentity3_.verified as verified1_2_ from user_ticket tickets0_ inner join ticket ticketenti1_ on tickets0_.tickets_ticket_id=ticketenti1_.ticket_id left outer join user userentity2_ on ticketenti1_.assigned_to_user_id=userentity2_.user_id left outer join user userentity3_ on ticketenti1_.belongs_to_user_id=userentity3_.user_id where tickets0_.user_user_id=?
The Entity Classes are:
TicketEntity.java
#Entity
#Table(name="ticket")
public class TicketEntity {
#Id
#Column(name="ticket_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="date_created")
#Temporal( TemporalType.TIMESTAMP )
private Date date_created;
#Column(name="status_id")
private int status_id;
//private TicketStatus status;
#Column(name="urgency_id")
private int urgency_id;
#ManyToOne
#JoinColumn(insertable=false, updatable=false)
private UserEntity belongs_to;
#ManyToOne
#JoinColumn(insertable=false, updatable=false)
private UserEntity assigned_to;
UserEntity.java
#Entity
#Table(name="user")
public class UserEntity {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="firstname")
private String firstname;
#Column(name="lastname")
private String lastname;
#Column(name="username")
private String username;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Transient
private String confirmpassword;
#Column(name="verified")
private boolean verified;
#Column(name="role_id")
private int role_id;
#OneToMany(fetch = FetchType.EAGER)
private List<TicketEntity> tickets;
Any help is appreciated,
Thanks!
In UserEntity.java, you need to add "mappedBy" for List<TicketEntity> tickets, like this:
#OneToMany(fetch = FetchType.EAGER, mappedBy="belongs_to")//why you have two UserEntity in TicketEntity.java?
private List<TicketEntity> tickets;
In TicketEntity.java, add (name = "user_id") to #JoinColumn for UserEntity belongs_to, like this:
#ManyToOne
#JoinColumn(name = "user_id", insertable=false, updatable=false)
private UserEntity belongs_to;
Same for private UserEntity assigned_to. You may need add another list for it in UserEntity.java if you want to query it too.