Spring + Hibernate don't create a Query - mysql

Can not create table in MYSQL, because something wrong with my Query or parameters in Entity, i don't understand. Everything i checked, everything i saw, but dont work. Please help
My Interface
public interface CourseDao extends JpaRepository <Course, Long> {
List <Course> findCourseBycourseName (String keyword);
#Query (value = "select * from courses as c where c.course_id in (select e.course_id from enrolled_in as e where e.student_id = :studentId)")
List <Course> getCourseBylistStudent (#Param ("studentId") Long studentId);
}
Entity Course
#Entity
#Table (name = "courses")
public class Course {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "course_id", nullable=false)
private Long courseId;
#Basic
#Column (name = "name", nullable=false, length = 45)
private String courseName;
#Basic
#Column (name = "duration", nullable=false, length = 45)
private String courseDuration;
#Basic
#Column (name = "description", nullable=false, length = 45)
private String courseDescription;
#ManyToOne (fetch = FetchType.LAZY)
#JoinColumn (name = "instructor_id", referencedColumnName = "instructor_id", nullable = false)
private Instructor instructor;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable (name = "enrolled_in",
joinColumns = {#JoinColumn (name = "course_id")},
inverseJoinColumns = {#JoinColumn (name = "student_id")})
private Set<Student> listStudent = new HashSet<>();
Student Entity
#Entity
#Table (name ="Students")
public class Student {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "student_id", nullable = false)
private Long studentId;
#Basic
#Column (name = "first_name", nullable = false, length = 45)
private String firstName;
#Basic
#Column (name = "last_name", nullable = false, length = 45)
private String lastName;
#Basic
#Column (name = "level", nullable = false, length = 45)
private String studentLevel;
#ManyToMany (mappedBy = "listStudent", fetch = FetchType.LAZY)
private Set <Course> courses = new HashSet<>();
#OneToOne (cascade = CascadeType.REMOVE)
#JoinColumn (name = "user_id", referencedColumnName = "user_id", nullable = false)
private User user;
Log
Error creating bean with name 'courseDao' defined in spring.dao.CourseDao defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.List spring.dao.CourseDao.getCourseBylistStudent(java.lang.Long); Reason: Validation failed for query for method public abstract java.util.List spring.dao.CourseDao.getCourseBylistStudent(java.lang.Long)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-6.0.2.jar:6.0.2]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[spring-context-6.0.2.jar:6.0.2]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[spring-context-6.0.2.jar:6.0.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-3.0.0.jar:3.0.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[spring-boot-3.0.0.jar:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-3.0.0.jar:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-3.0.0.jar:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[spring-boot-3.0.0.jar:3.0.0]
at spring.CourseSystemApplication.main(CourseSystemApplication.java:12) ~[classes/:na]
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.List spring.dao.CourseDao.getCourseBylistStudent(java.lang.Long); Reason: Validation failed for query for method public abstract java.util.List spring.dao.CourseDao.getCourseBylistStudent(java.lang.Long)
at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:88) ~[spring-data-commons-3.0.0.jar:3.0.0]
at
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List spring.dao.CourseDao.getCourseBylistStudent(java.lang.Long)
Caused by: org.hibernate.query.SemanticException: A query exception occurred [select * from courses as c where c.course_id in (select e.course_id from enrolled_in as e where e.student_id = :studentId)]
... 48 common frames omitted
In other interface everything work, but with CourseDao have some problem, if you know, please help me!

Use nativeQuery=true when using MySQL queries in spring data jpa.
#Query(nativeQuery = true, value = "your query")

Related

Cannot create Entity in DB without exception

I run my app, and everything work nicely. My entities are created in the DB, but in spite of this, I have next exception.
Error executing DDL "alter table user add constraint UK_ob8kqyqqgmefl0aco34akdtpe unique (email)" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table user add constraint UK_ob8kqyqqgmefl0aco34akdtpe unique (email)" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:502) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:486) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:402) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:176) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:144) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:128) ~[hibernate-core-6.1.5.Final.jar:6.1.5.Final]
... 35 common frames omitted
My properties table is create
My Entities
Entity
#Table (name = "User")
public class User {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "user_id", nullable = false)
private Long userId;
#Basic
#Column (name = "email", nullable = false, length = 4096, unique = true)
private String userEmail;
#Basic
#Column (name = "password", nullable = false, length = 4096)
private String userPassword;
#ManyToMany (fetch = FetchType.EAGER)
#NotFound(action = NotFoundAction.IGNORE)
#JoinTable (name = "user_role",
joinColumns = {#JoinColumn (name = "user_id")},
inverseJoinColumns = {#JoinColumn (name = "role_id")})
private Set <Role> roles = new HashSet<>();
#OneToOne (mappedBy = "user")
private Student student;
#OneToOne (mappedBy = "user")
private Instructor instructor;
public User () {}
If you know please say what I need to do, thanks!

Spring delete row of join table

I have two entities User:
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long userID;
#Column(name = "userHashedPassword")
private String password;
#Column(name = "userName")
private String userName;
#Column(name = "userEmail")
private String email;
#Transient
private List<String> groups = new LinkedList<>();
#ManyToMany
#JoinTable(name = "UserRoles",
joinColumns = #JoinColumn(
name = "userID"),
inverseJoinColumns = #JoinColumn(
name = "roleID"))
private Set<Role> roles = new HashSet<>();
#OneToMany(mappedBy = "user")
private Set<Rating> ratings;
protected User(){}
public User(String userHashedPassword, String userName, String email, Set<Role> roles){
this.password = userHashedPassword;
this.userName = userName;
this.email = email;
this.roles = roles;
}
//getters and setters
}
And Group:
#Table(name="FocusGroups")
#Entity
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "groupID")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long groupID;
private String groupName;
#ManyToMany
#JoinTable(name = "GroupMembers",
joinColumns = #JoinColumn(
name = "groupID"),
inverseJoinColumns = #JoinColumn(
name = "userID"))
private Set<User> groupMembers = new HashSet<>();
#ManyToOne(fetch = FetchType.EAGER, optional = true)
#JoinColumn(name="frameworkID", nullable = true)
private Framework framework;
public Group(){}
public Group(String groupName, Set<User> groupMembers, Framework framework) {
this.groupName = groupName;
this.groupMembers = groupMembers;
this.framework = framework;
}
//getters setters
}
When I delete a User, I want to remove them from group members, however it fails due to foreign key constraint: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (capripol.groupmembers, CONSTRAINT FK98tbu0sjfsn1m5p340dn0v8wo FOREIGN KEY (userID) REFERENCES users (userID))
How do I work around this?
Well, I will try to answer: First of all, it is rather strange you refer on Groups in user
entity like that:
#Transient
private List<String> groups = new LinkedList<>();
It this case, you will not have a column group in user table in database, hence you have to first perform removal from group_members for an all groups:
delete from group_members where userid = <user_id_you_want_to_remove>;
And only after your JoinTable table does not contain any refers to user with <user_id_you_want_to_remove>, than you can execute
delete from users where userid = 1;
Note: there is no matter you do it by spring data (e.g. deleteById(Long id) and using #Query annotation specify the query above in SQL or HQL, up to you) - this will work. But I highly recommend you to reconsider you database structure - it is not cute to store only one entity.

Failed to convert from type [java.lang.Object[]] to type [#org.springframework.data.jpa.repository.Query

I have spring boot project using JPA/Hibernate, MySQL. I have three dao classes that have a many to many relationship.
The Poko classes look like this
Product
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "price")
private Double price;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(
name = "product_extra",
joinColumns = #JoinColumn(name="product_id"),
inverseJoinColumns = #JoinColumn(name="extra_id")
)
private List<Extra> extras = new ArrayList<>();
//constructor getters and setters
}
ProductExtra
#Entity
#Table(name = "product_extra")
public class ProductExtra {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "product_id")
private Integer productId;
#Column(name = "extra_id")
private Integer extraId;
//constructor getters and setter
}
Extra
#Entity
#Table(name = "extra")
public class Extra {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false, columnDefinition = "integer")
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "price")
private Double price;
#ManyToMany(mappedBy = "extras")
private List<Product> products = new ArrayList<>();
//constructor getters and setters
}
The Extra repository with the query
public interface ExtraRepository extends JpaRepository<Extra, Integer> {
#Query("SELECT e.id, e.name, e.price FROM Extra e INNER JOIN ProductExtra pe ON e.id = pe.extraId WHERE pe.productId = ?1")
List<Extra> findExtraById(Integer productId);
}
The mapping in my controller
#GetMapping("/product/{productId}")
public List<Extra>getExtraById(#PathVariable("productId") final Integer productId){
return extraRepository.findExtraById(productId);
}
I am trying to make a many to many query to select The extras in each product, i am however getting this error Failed to convert from type [java.lang.Object[]] to type [#org.springframework.data.jpa.repository.Query the error message surprisingly also contains the results i want. Not sure what am doing wrong
Remove the SELECT clause:
#Query("FROM Extra join e.productExtra WHERE pe.productId = ?1")
Also keep in mind, that you not write an SQL Query, You work on Object, so for join you use the mapped property

path expected for join JPA Hibernate MySQL

I'm using composite PK in my app with 2 tables and one joining table.
I wrote this query for function:
#Repository
public interface HospitalDoctorDao extends JpaRepository<HospitalDoctor, Integer>{
#Query("select hd from HospitalDoctor hd join hospital on hd.hospital_id=hospital.id join doctor on hd.doctor_id = doctor.id where hospital_id = ?1 and doctor_id = ?1")
HospitalDoctor findByHospitalIdAndDoctorId(int hospital_id, int doctor_id);
}
and I am getting error Path expected for file! In MySQL everything is working. How Hibernate works in this case? How I should write this query? Here is my #Entity of join table:
#Entity
#Table(name = "hospital_doctor")
public class HospitalDoctor {
#Embeddable
static class HosdocPK implements Serializable {
private int hospitalId;
private int doctorId;
}
#EmbeddedId
#JsonBackReference
public HosdocPK hosdocPK;
#JsonManagedReference
#MapsId("DoctorId")
#ManyToOne(optional = false)
#JoinColumn(name = "doctorId", referencedColumnName = "id")
private Doctor doctor;
#JsonManagedReference
#MapsId("HospitalId")
#ManyToOne(optional = false)
#JoinColumn(name = "hospitalId", referencedColumnName = "id")
private Hospital hospital;
#Column(name = "Id")
private int id;
#Temporal(TemporalType.DATE)
private Date contract_start_date;
#Temporal(TemporalType.DATE)
private Date contract_end_date;
private String position;
private String supervisor;
private boolean part_time;
Getters and setters
}
Your query is incorrect.
Try:
select hd from HospitalDoctor hd where hd.hospital.id = ?1 and hd.doctor.id = ?2

Converting SQL query to JPA NamedQuery

I'm trying to implement a Keyword search functionality that returns a List of Keyword entities based on a field text match.
Right now, the query
select * from photo_keywords pk
inner join keywords k on pk.photo_id = k.keyword_id
inner join photos p on pk.keyword_id = p.photo_id
where k.keyword LIKE "%$SOME_SEARCH_VALUE%";
returns all matching photos for a given keyword search. I'd like to have this adapted to a #NamedQuery with the following Entity objects:
#Entity
#Table(name = "keywords")
public class Keyword implements Serializable{
#Id
#Column(name = "keyword_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String keyword;
#ManyToMany(mappedBy = "keywords")
private List<Photo> photos;
//getters and setters
}
and
#Entity
#Table(name = "photos")
public class Photo implements Serializable{
#Id
#Column(name = "photo_id", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "photo_name", nullable = false)
private String photoName;
#Column(name = "photo_path", nullable = false)
private String photoPath;
#Column(name = "upload_date", nullable = false)
private Date uploadDate;
#Column(name = "view_count", nullable = false)
private int viewCount;
#Column(name = "capture_date", nullable = false)
private Date captureDate;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "photo_metadata")
#MapKeyColumn(name = "metadata_name")
#Column(name = "metadata_value")
private Map<String, String> photoMetadata;
#ManyToMany
#JoinTable(name = "photo_keywords",
joinColumns = #JoinColumn(name = "keyword_id"),
inverseJoinColumns = #JoinColumn(name = "photo_id"))
public List<Keyword> keywords;
//getters and setters
}
This creates a join table photo_keywords, rather than a JoinColumn.
What I've tried so far with the Keyword entity:
#NamedQueries({
#NamedQuery(
name = "findKeywordByName",
query = "SELECT keyword from Keyword k WHERE k.keyword = :keyword"
)
})
which is executed via
public Keyword findKeywordByString(String keyword){
Keyword thisKeyword;
Query queryKeywordExistsByName = getEntityManager().createNamedQuery("findKeywordByName");
queryKeywordExistsByName.setParameter("keyword", keyword);
try {
thisKeyword = new Keyword((String) queryKeywordExistsByName.getSingleResult());
} catch (NoResultException e){
thisKeyword = null;
}
return thisKeyword;
}
This returns the Keyword, but with the photos property being null. This is to be expected, since I'm only selecting the keyword property. How can I adapt the SQL query above to a #NamedQuery?