I would like to make a JPA query to count how many records are with a specific foreign key.
Entities:
#Entity(name = "person")
#Inheritance(strategy = InheritanceType.JOINED)
public class Person {
#Id
private Long id;
private String firstName;
private String lastName;
private String phoneNumber;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinColumn(name = "ADRESS_FK")
private ADDRESS address;
}
#Entity(name = "address")
public class Address {
#Id
private Long id;
private String country;
private String city;
private String street;
private String number;
}
And this is what i am trying, how would this look in JPA?
public Long getOccurences( Long id ) {
Query query = _entityManager.createQuery( "Select count(*) from Persons p where p.address = ?1" );
query.setParameter( 1, id );
return query.getSingleResult() );
}
Related
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'm building app to learn Hibernate on PostgreSQL. And I'm currently trying to add variable to database that has OneToOne relationship.
First, I create two tables in my database with schema below. On person_detail table it has primary key that's also foreign key to person table.
Then I created two classes, Person and PersonDetail. PersonDetail is child of Person that has OneToOne relationship. And I use code below to add person with personDetail as attribute.
Person person = new Person(
"Rick",
1.7,
dateFromString("1969-4-2"),
new Date()
);
PersonDetail personDetail =
new PersonDetail("myemail#email.com", "Marley");
person.setPersonDetail(personDetail);
session.beginTransaction();
session.save(person);
session.save(personDetail);
session.getTransaction().commit();
System.out.println(person.toString());
But the problem with code above is that Hibernate execute child query first instead of parent query.
Hibernate: insert into person_detail (address, email) values (?, ?)
And since person still empty, we cannot insert any row to person_detail because it violates foreign key constraint.
Is there a way to solve this?
Thanks!
In case some one want to check how I annotate those two classes, I put the code below.
#Entity
#Table(name="person")
#Data
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#Column(name="height")
private double height;
#Column(name="birth_date")
private Date dateBirth;
#Column(name="last_seen")
private Date lastSeen;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id")
private PersonDetail personDetail;
public Person() {}
public Person(String name, double height, Date dateBirth, Date lastSeen){
this.name = name;
this.height = height;
this.dateBirth = dateBirth;
this.lastSeen = lastSeen;
}
}
#Data
#Entity
#Table(name="person_detail")
public class PersonDetail {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name="email")
private String email;
#Column(name="address")
private String address;
public PersonDetail(){}
public PersonDetail(String email, String address){
this.email = email;
this.address = address;
}
}
I see that you have primary key in table person_details as foreign key to person table, you can use #PrimaryKeyJoinColumn like this:
#Entity
#Table(name="person")
#Data
public class Person {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "height")
private String height;
#OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private PersonDetail personDetail;
public Person() {}
public Person(String name, String height) {
this.name = name;
this.height = height;
}
}
#Data
#Entity
#Table(name="person_detail")
public class PersonDetail {
#Id
#Column(name="id")
private Long id;
#Column(name="email")
private String email;
#OneToOne
#MapsId
#JoinColumn(name = "id", referencedColumnName = "id")
private Person person;
public PersonDetail(){}
public PersonDetail(String email){
this.email = email;
}
}
And if you save your entity, don't forget set Person to PersonDetails:
Person person = new Person("Rick", "1.7");
PersonDetail personDetail = new PersonDetail("myemail#email.com");
personDetail.setPerson(person);
person.setPersonDetail(personDetail);
repository.save(person);
I have a problem with the relationship oneToMany. I created tables in SQLite DB, this is my tables:
I created the two models CategoryModel and ProductModel.
ProductModel is:
#Entity
#Table(name = "Product_Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class ProductModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long product_id;
private Long category_id;
private String name;
private String description;
private int numberOfProduct;
private String image;
private int price;
#JoinColumn(name = "country_id", nullable = false)
private CategoryModel category;
//geter's and seter's
}
My CategoryModel:
#Entity
#Table(name = "Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class CategoryModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String category_name;
private String category_description;
private String image_path;
#OneToMany( mappedBy = "category")
private Set<ProductModel> category;
//Geter's and Seter's
My Repository:
public interface CategoryRepository extends JpaRepository<CategoryModel, Long> {
#Query("SELECT * "
+ "FROM Product_Category d INNER JOIN d.categoryModel e")
List<ProductModel> fetchEmpDeptDataInnerJoin();
}
I do not understand where I make a mistake. I have this error:
Could not determine type for:
com.dar.darkozmetika.models.CategoryModel, at table: product_category,
for columns: [org.hibernate.mapping.Column(category)]
1) Add #ManyToOne annotation:
#ManyToOne
#JoinColumn(name = "country_id", nullable = false)
private CategoryModel category;
2) Remember that you are using JPQL, not SQL (unless you sent native="true"):
#Query("SELECT p "
+ "FROM ProductModel p INNER JOIN p.category c")
I have the following entities:
Person.java
#Table(name = persons)
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "UserID", nullable = false)
private Long userId;
#Column(name = "Employeenumber", nullable = false) private String employeeNumber;
#Column(name = "Firstname", nullable = false) private String firstName;
#Column(name = "Lastname", nullable = false) private String lastName;
public User() { }
public User(String employeeNumber, String firstName, String lastName) {
super();
this.employeeNumber = employeeNumber;
this.firstName = firstName;
this.lastName = lastName;
}
/*
getter and setters
...
*/
}
Personhistory.java
#Entity
#Table(name = personhistory)
public class Personhistory {
#Id
#Column(name = "UserID", nullable = false)
private Long userId;
#Column(name = "Fromdate", nullable = false) private Date fromDate;
#Column(name = "Todate", nullable = false) private Date toDate;
#Column(name = "TeamID", nullable = false) private Integer teamId;
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "UnikId", nullable = false)
private Integer unikId;
public Userhistory() {
}
public Userhistory(Long userId, Date fromDate, Date toDate, int teamId) {
super();
this.userId = userId;
this.fromDate = fromDate;
this.toDate = toDate;
this.teamId = teamId;
}
/*
Getters and setters
...
*/
}
Team.java
#Entity
#Table(name = "team")
public class Team {
#Id
#Column(name = "TeamID")
#GeneratedValue(strategy = GenerationType.AUTO)
private int teamId;
#Column(name = "TeamNumber") private String teamNumber;
public Team() {}
public Team(String teamNumber) {
super();
this.teamNumber = teamNumber;
}
/*
Getters and setters
...
*/
}
I want to make a API call like this:
localhost:8080/users/{employee}
And get back an object containing the person (His emp-number, firstname and lastname), when he was at the team and what team that is.
If I were to write this query in MSSQL, it would look like this:
select * from persons p
join personhistory ph on ph.UserID = p.UserID
and ph.Fromdate <= cast(getdate() as date)
and ph.Todate >= cast(getdate() as date)
join team t on t.TeamID = ph.TeamID
where u.Employeenumber = '999'
I have searched around for different solutions like HQL, JPQL, Criteria and so on, but I'm unable to make it work.
Any help would be much appreciated.
AFAIK Hibernate 5.1 provides more generic joins but with prior versions you'd either have to use a cross join and add the conditions in the where-clause or provide a real relation between the entities and join on that relation (using the "with" keyword for additional join conditions).
Example (note that I left out many annotations for simplicity):
class Person {
#OneToMany( mappedBy = "user" )
Collection<Personhistory> history;
...
}
class Personhistory {
#ManyToOne
Person user;
#ManyToOne
Team team;
...
}
Then the query could become
select p, ph, t from Person p
join p.history ph with ph.fromdate <= :date and ph.toDate >= :date
join ph.team t
where p.employeeNumber = :number
I am new to JPA and doing a small sample to learn about it.
But I got one problem below, please help me out, and please explain why:
I have class Customer.java, which is mapped to table customer in db:
#Entity
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id_customer")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
// accountNumber field maps with accountNumber column in Account table
#Column(name = "loginId", unique = true)
private String loginId;
#Column(name = "password")
private String password;
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
#Column(name = "address")
private String address;
#Column(name = "email")
private String email;
#Column(name = "phone")
private String phone;
#OneToMany(mappedBy="customer")
private List<Account> accountList;
#OneToMany(mappedBy="customer")
private List<Card> cardList;
// getters and setters goes here
}
The above class has two lists, accountList and cardList, their generic Class (Card and Account) extends BaseInfo using Single table Inheritance.
Here is my BaseInfo.java:
#Entity
#Table(name = "account")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public class BaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "number")
private String number;
#Column(name = "availableNumber")
private Long availableNumber;
//getter and setter here
}
Class Card.java:
#Entity
#Table(name = "account")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorValue(value = "C")
public class Card extends BaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "cardType")
private String cardType;
#ManyToOne
#JoinColumn(name = "id_customer")
private Customer customer;
//getter and setter
}
And class Account.java:
#Entity
#Table(name = "account")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorValue(value = "A")
public class Account extends BaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "accountName")
private String accountName;
#Column(name = "accountType")
private String accountType;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "dt_created")
private Date createdDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "dt_lst_updt")
private Date lastUpdatedDate;
#ManyToOne
#JoinColumn(name = "id_customer")
private Customer customer;
//getter, setter
}
Then, I do a query that query customer from database with loginid and password, like this:
entityTransaction.begin();
TypedQuery<Customer> query = entityManager.createQuery(
"SELECT c FROM " + Customer.class.getName()
+ " c Where c.loginId= :loginId", Customer.class);
query.setParameter("loginId", loginId);
res = query.getSingleResult();
entityTransaction.commit();
The code run with no error, but the result is somethings strange to me: When I debug (or print out the result to jsp), accountList or cardList contains all Account of that customer, just like they don't care about the 'discriminator' column.
I have 2 questions:
How can I archive the goal that listCard contains only Card (discrimination = c) and listAccount contains only Account (discriminator = a) ?
Is there an alternative way to query listCard or listAccount without query the customer first (like I use) ??
Thank in advance! :D
I'm not sure if it's a JPA restriction or a Hibernate-specific restriction, but you may not use the same column to map two different associations.
You should use something like car_customer_id to map the association between customer and cards, and account_customer_id to map the association between customer and accounts.