trying to run a named query - java

I’m doing the following:
#Entity
#SqlResultSetMapping(name="getxxxx",
entities=#EntityResult(xxxx.class,
fields = {
#FieldResult(name="x1", column = "x1"),
#FieldResult(name="x2", column = "x2")}))
#NamedNativeQuery(name=" getxxxx ",
query="select x1, x2 from yyyy",
resultSetMapping=" getxxxx ")
} )public class xxxx{
.
.
.
public xxxx() {
}
i get an error:
"Table "xxxx" cannot be resolved", the class xxxx is not a table mapped into my source,
I’m trying to query the DB and return the results into my class
is it possible?

In this situation the first thing I would try would be to remove the #Entity annotation. And then change either the class name or the native query name so that one of them is "xxxx" and one of them is "zzzz," so that I was sure I knew which thing the runtime was complaining about.

It sounds like xxxx should not be an entity bean, since JPA is not happy with returning results in non-entity beans. You must instead call createNativeQuery with just the SQL String. Then call query.getResultList() to fetch the result as a List(Object[]) and use this to fill your non entity result bean.
A few years back I wrote a blog post, that might help you perform advanced native queries with JPA.

Yes, this is possible, but a little tricky. Here's a complex example that should cover most of the bases. In this example:
You have an INVOICE object with a due date;
Each INVOICE has a many-to-one relationship with a COMPANY;
Each INVOICE also has a zero- or one-to-many relationship with a set of ITEMS
Here is the schema:
CREATE TABLE "public"."invoice" (
id SERIAL,
company_id int,
due_date date,
PRIMARY KEY(id)
);
CREATE TABLE "public"."item" (
id SERIAL,
invoice_id int,
description text,
PRIMARY KEY(id)
);
CREATE TABLE "public"."company" (
id SERIAL,
name text,
PRIMARY KEY(id)
);
The INVOICE object (incredibly convoluted example for the sake of completeness):
#Entity
#Table(name = "invoice")
#Loader(namedQuery = "loadInvoiceObject")
#NamedNativeQuery(name="loadInvoiceObject",
query="SELECT " +
"inv.id," +
"inv.due_date," +
"co.*," +
"it.*," +
"FROM invoice inv " +
"JOIN company co ON co.id = inv.company_id " +
"LEFT OUTER JOIN item it ON it.invoice_id = inv.id " +
"WHERE inv.id = :id",
resultSetMapping = "invoicemap")
#SqlResultSetMapping(name = "invoicemap",
entities = {
#EntityResult(entityClass = Invoice.class),
#EntityResult(entityClass = Company.class),
#EntityResult(entityClass = Item.class)
}
)
public class Invoice {
private Integer id;
private Date dueDate;
private Company company;
private List<Item> items = new ArrayList<Item>();
public Invoice() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "due_date")
#Temporal(TemporalType.DATE)
public Date getDueDate() { return dueDate; }
public void setDueDate(Date dueDate) { this.dueDate = dueDate; }
#ManyToOne(optional = false)
#JoinColumn(name = "company_id", nullable = false)
public Company getCompany() { return company; }
public void setCompany(Company company) { this.company = company; }
#OneToMany(mappedBy = "invoice")
public List<Item> getItems() { return items; }
public void setItems(List<Item> items) { this.items = items; }
}
The ITEM object:
#Entity
#Table(name = "item")
public class Item {
private Integer id;
private String description;
private Invoice invoice;
public Item() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "description")
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
#ManyToOne(optional = false)
#JoinColumn(name = "invoice_id", nullable = false)
public Invoice getInvoice() { return invoice; }
public void setInvoice(Invoice invoice) { this.invoice = invoice; }
}
The COMPANY object:
#Entity
#Table(name = "company")
public class Company {
private Integer id;
private String name;
private List<Invoice> invoices = new ArrayList<Invoice>();
public Company() { /* no-args constructor */ }
#Id
#Column(name = "id", nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#Column(name = "name")
public String getName() { return name; }
public void setName(String name) { this.name = name; }
#OneToMany(mappedBy = "company")
public List<Invoice> getInvoices() { return invoices; }
public void setInvoices(List<Invoice> invoices) { this.invoices = invoices; }
}

Related

How to save with default value using Spring JPA?

Recently I switched into Spring Data JPA and I am wondering how is it possible to save a new object into the database with some default values.
In my example I have to save a book into my database, but, in the owner column, I need to put the value 0.
So, this how I did that with JDBC, and it works amazingly well.
public void save(Book book){
jdbcTemplate.update("INSERT INTO book(name,author,yearOfProduction,owner) VALUES (?, ?, ?, 0)",
book.getName(),book.getAuthor(),book.getYearOfProduction());
}
Now I want to do the same with Spring Data JPA. Here is my save function:
BookService
#Transactional
public void save(Book book)
{
bookRepository.save(book);
}
I have two objects: Person and Book. The relationships are: one person can have many books and one book has one owner. Here are my Person and Book classes:
Book
#Entity
#Table(name = "book")
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id",nullable = false)
private int id;
#Column(name="name")
#NotEmpty(message = "Book name can't bee empty")
private String name;
#Column(name="author")
#NotEmpty(message = "Author name can't bee empty")
private String author;
#Column(name="yearOfProduction")
#NotNull(message = "Year of production can't bee empty")
#Min(value = 0,message = "year must be more than 1900")
private int yearOfProduction;
#ManyToOne
#JoinColumn(name = "owner_id", referencedColumnName = "id")
private Person owner;
public Book(String name, String author, int yearOfProduction) {
this.name = name;
this.author = author;
this.yearOfProduction = yearOfProduction;
}
public Book(){
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getYearOfProduction() {
return yearOfProduction;
}
public void setYearOfProduction(int yearOfProduction) {
this.yearOfProduction = yearOfProduction;
}
}
Person|
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
#NotEmpty(message = "Please enter the name")
#Size(min = 1, max = 30, message = "Length must be 2-30 symbols")
//make regex with ФИО;
private String name;
#Column(name = "ageOfBirth")
#Min(value = 0, message = "age of birth must be more than 0")
private int ageOfBirth;
#OneToMany(mappedBy = "owner")
private List<Book> books;
public Person() {
}
public Person(String name, int ageOfBirth) {
this.name = name;
this.ageOfBirth = ageOfBirth;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAgeOfBirth() {
return ageOfBirth;
}
public void setAgeOfBirth(int ageOfBirth) {
this.ageOfBirth = ageOfBirth;
}
}
I guess this is impossible to make with Spring Data JPA? So, I made it with by adding JdbcTemplate and I definitely think it is a hard-coding approach to use Spring DATA and JdbcTemplate together.
It's also unable to make with database. Down below i am using the default definition of postgres and still get null's when create a new book.
https://www.baeldung.com/jpa-default-column-values
create table book(
id int primary key generated by default as identity,
name varchar(250) not null,
author varchar(250) not null,
yearOfProduction int not null,
owner_id int default 0 references person(id)
)
#egeorge answered my question. It is impossible to input 0 into owner table.
Since 0 has a special value, and is not a real person record, there should not be any value in that field. null is the appropriate value for a join column that is not joined to an actual record. You will need to change the logic that interprets 0 as "free" to check for null instead. (I am surprised your database let you do that to begin with. Foreign key constraints will normally reject a value that is not present in the referred table.)

Supported keywords inside method names in Spring JPA

How do I write the method name for the below query:
#Query("SELECT r.skill, r.rating, count(r) FROM AssociateRating r "
+ "where updatedTime = ( select max(updatedTime) from AssociateRating a "
+ "where r.associate = a.associate ) GROUP BY r.skill, r.rating")
List<Object[]> findCountMostRecent();
Please find below the model:
#Entity
#Table(name = "associate_ratings")
public class AssociateRating {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String associate;
#ManyToOne
#JoinColumn(name = "skill_id")
private Skill skill;
private int rating;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_time")
private Date updatedTime;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAssociate() {
return associate;
}
public void setAssociate(String associate) {
this.associate = associate;
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public Date getUpdatedTime() {
return updatedTime;
}
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
}
/**
* Skill Model
*/
#Entity
#Table(name = "skills")
public class Skill {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I am getting exception when trying to extract records from associate_ratings
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'updatedTime' in 'where clause'
Could you please advise what is wrong here?
Could you also please let me know how do we name Spring JPA findXX methods in such cases?
Indeed there is no 'updatedTime' column in your table.
The column name is 'updated_time', as shown in your #Entity updatedTime variable.
Now in case you want to create method name using JPA keywords I guess it is not possible in your query for several reasons:
You can't select specific columns (r.skill, r.rating, count(r)), but you should select them all.
You can't have nested queries.
There is no GroupBy keyword
You can find all the JPA supported keywords here: 2.3 Query methods
So in your case, you should go for the #Query approach.

How to create a many to many relationship with extra columns in jhipster?

The jhipster doesn't support create many to many relationships with extra fields.
What is the best way to create many to many association with extra columns in jhispter? Should i create a two one-to-many relationship with extra fields?
Using JHipster Domain Language (JDL), a #ManytoMany holding extra properties (columns) can be easily achieved using an association entity and two ManyToOne relationships. See below:
entity Foo{
...
}
entity Bar{
...
}
entity FooBarAssociation{
extraProperty1 String
extraProperty2 String
...
}
relationship ManyToOne {
FooBarAssociation{foo} to Foo{bars}
FooBarAssociation{bar} to Bar{foos}
}
You will have to do it manually.
this post describes how: https://hellokoding.com/jpa-many-to-many-extra-columns-relationship-mapping-example-with-spring-boot-maven-and-mysql/
In general, as #Antares42 said, you should create an entity for the Many-To-Many table like so:
first entity:
#Entity
public class Book{
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Book() {
}
public Book(String name) {
this.name = name;
bookPublishers = new HashSet<>();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
secound entity:
#Entity
public class Publisher {
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Publisher(){
}
public Publisher(String name){
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "publisher")
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
Join table entity:
#Entity
#Table(name = "book_publisher")
public class BookPublisher implements Serializable{
private Book book;
private Publisher publisher;
private Date publishedDate;
#Id
#ManyToOne
#JoinColumn(name = "book_id")
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#Id
#ManyToOne
#JoinColumn(name = "publisher_id")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
#Column(name = "published_date")
public Date getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}
}
This entity describes the relationship between Book and Publisher and the extra field is published_date
Let's say you have entities like Movie, Rater and needs a join table Ratings. You can write a JDL script like the following:
entity Movie { title String}
entity Rater { name String}
entity Rating { value Integer} //the extra field
relationship ManyToMany {
Rating{rater(name)} to Rater,
Rating{movie(title)} to Movie
}
save it in file.jdl in the project folder, open cmd type
jhipster import-jdl file.jdl
and you have everything

Hibernate error: Illegal Attempt to deference collection

Hello I have a one to many relationship between a reservation and rooms and its unidirectional. A reservation might have one to several rooms. Now I'm trying to search if a room is available based on certain dates, and type of room(i.e a king or queen).
My solution:
Find Rooms that are not present in the reservation table based and also based on the date criteria.
Room model:
#Entity
#Table(name="room")
public class Room implements java.io.Serializable {
private static final long serialVersionUID = 10L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="roomId", nullable = false)
private long Id;
#Column(name="roomNumber", length = 4, nullable = false) //room number with max length of 4 digits
private String roomNumber;
#Column(name="type", nullable = false, length=10) //queen or king
private String roomType;
#Column(name="properties", nullable = false, length=15) //smoking or non-smoking
private String roomProperties;
#Column(name="price", columnDefinition = "DECIMAL(10,2)", nullable = false) //sets the precision of price to 2 decimal places
private double price;
public Room() {}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public long getId() {
return Id;
}
public void setId(long id) {
this.Id = id;
}
public String getRoomNumber() {
return roomNumber;
}
public void setRoomNumber(String roomNumber) {
this.roomNumber = roomNumber;
}
public String getRoomType() {
return roomType;
}
public void setRoomType(String roomType) {
this.roomType = roomType;
}
public String getRoomProperties() {
return roomProperties;
}
public void setRoomProperties(String roomProperties) {
this.roomProperties = roomProperties;
}
}
Reservation Table:
#Entity
#Table(name="Reservation")
public class Reservation implements Serializable {
private static final Long serialVersionUID = 100L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="reservation_Id", nullable = false)
private long Id;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
#Column(name="CheckInDate")
private Date checkInDate;
#Column(name="CheckOutDate")
private Date checkOutDate;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "guestId", nullable = false)
private Guest guest;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "ReservedRooms", joinColumns = {#JoinColumn(name="resId",
referencedColumnName = "reservation_Id")}, inverseJoinColumns = {#JoinColumn(name="roomId",
referencedColumnName = "roomId")})
private List<Room> roomList;
#Column(name="roomsWanted")
private int roomsWanted;
public int getRoomsWanted() {
return roomsWanted;
}
public void setRoomsWanted(int roomsWanted) {
this.roomsWanted = roomsWanted;
}
public Date getCheckInDate() {
return checkInDate;
}
public void setCheckInDate(Date checkInDate) {
this.checkInDate = checkInDate;
}
public Date getCheckOutDate() {
return checkOutDate;
}
public void setCheckOutDate(Date checkOutDate) {
this.checkOutDate = checkOutDate;
}
public Guest getGuest() {
return guest;
}
public void setGuest(Guest guest) {
this.guest = guest;
}
public List<Room> getRoomList() {
return roomList;
}
public void setRoomList(List<Room> roomList) {
this.roomList = roomList;
}
}
Now method to perform the search availability:
#Override
#Transactional
#SuppressWarnings("unchecked")
public boolean checkAvailability(SearchCriteria searchCriteria) {
String hql = "from Room as r where r.roomType = :roomType1 and r.roomProperties = :roomProperties1 " +
"and r.Id not in (Select res.roomList.Id from Reservation as res left outer join res.roomList " +
"where res.checkInDate <=:checkInDate1 and res.checkOutDate >= :checkOutDate1 " +
" and R.Id = res.roomList.Id) ";
Query query = getSession().createQuery(hql);
query.setParameter("roomType1", searchCriteria.getRoomType());
query.setParameter("roomProperties1", searchCriteria.getRoomProperties());
query.setParameter("checkInDate1", searchCriteria.getCheckInDate());
query.setParameter("checkOutDate1", searchCriteria.getCheckOutDate());
List<Room> roomList = query.list();
if(roomList.isEmpty()) {
return true;
}
return false;
}
But it complains and gives the error:
illegal attempt to dereference collection [reservatio1_.reservation_Id.roomList] with element property reference [Id]
Please what I'm doing wrong as I'm new to hibernate
When you join a collection, you have to name it. You can't use it directly (dereference).
in (Select ROOMS.Id from Reservation as res
left outer join res.roomList AS ROOMS
where res.checkInDate <=:checkInDate1 and res.checkOutDate >= :checkOutDate1
and R.Id = ROOMS.Id)

hibernate.hbm2ddl.auto=update don't work

I have model. there is this part:
model was mapped by jpa annotations.Everywhere I use fetchType = EAGER. If I load vacancy from database, I have 2 duplicates status_for_vacancy objects.
I use property hbm2ddl.auto = update.
If I make new schema of database and fill data, I haven't duplicates status_for_vacancy objects.
It really?
code:
vacancy:
#Entity
#Table(name = "vacancy")
#XmlRootElement(name="vacancy")
public class Vacancy {
private List<VacancyStatus> statusList = new LinkedList<VacancyStatus>();
#OneToMany(mappedBy = "vacancy", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<VacancyStatus> getStatusList() {
return statusList;
}
public void setStatusList(List<VacancyStatus> statusList) {
this.statusList = statusList;
}
}
status_for_vacancy:
#Entity
#Table(name = "status_for_vacancy")
public class StatusForVacancy extends AbstractStatus {
public StatusForVacancy() {
super();
}
public StatusForVacancy(Integer id, String name) {
super(id, name);
}
}
#MappedSuperclass
#XmlRootElement
public abstract class AbstractStatus {
private Integer id;
private String name;
public AbstractStatus() {
super();
}
public AbstractStatus(String name) {
super();
this.name = name;
}
public AbstractStatus(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name ="id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name")
#NotEmpty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
vacancy_status:
#Entity
#Table(name = "vacancy_status")
public class VacancyStatus extends AbstractHistoryStatus {
private Vacancy vacancy;
private StatusForVacancy status;
public VacancyStatus() {
super();
}
public VacancyStatus(Integer id, User author, Date date,
Vacancy vacancy, StatusForVacancy status) {
super(id, author, date);
this.vacancy = vacancy;
this.status = status;
}
#ManyToOne
#JoinColumn(name = "vacancy_id")
public Vacancy getVacancy() {
return vacancy;
}
public void setVacancy(Vacancy vacancy) {
this.vacancy = vacancy;
}
#ManyToOne
#JoinColumn(name = "status_id")
public StatusForVacancy getStatus() {
return status;
}
public void setStatus(StatusForVacancy status) {
this.status = status;
}
}
#MappedSuperclass
public abstract class AbstractHistoryStatus {
private Integer id;
private User author;
private Date date;
public AbstractHistoryStatus() {
}
public AbstractHistoryStatus(Integer id, User author, Date date) {
super();
this.id = id;
this.author = author;
this.date = date;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
#Column(name="creation_date")
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
It is all mapping code for these entities.
in debugger:
both id==500 ==> hibernate understand, that it is same objects.
I try add all data from old database to new database - I get old error(
I fix cause of appearance of this problem. It appearances if I add record to note table:
I highly recommend you write equals() and hashCode() methods. The standard equals()/hashCode() implement referential equality (do 2 objects reference the same memory location). So if hibernate has 2 of the 'same' object in memory, but they don't reference the same memory location then you will see the object show up twice. But if you implement equals() based on primary key being equal, then even if there are two copies of the same object in memory, Hibernate won't give you duplicates.
See the JPA spec:
2.4 Primary Keys and Entity Identity
Every entity must have a primary key. ... The value of its primary key
uniquely identifies an entity instance within a persistence context
and to EntityManager operations
Also see this SO post.

Categories

Resources