#Query Spring Data JPA Update Not Working - sql

Here is my User entity:
#Entity
#Table(name="users")
public class User implements IBaseEntity<User> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long userId;
#Column(unique = true)
#NotNull
private String username;
#Column(unique = true)
#NotNull
private String email;
#Column
#NotNull
private String password;
// #formatter:off
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_roles",
joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") })
// #formatter:on
private List<Role> roles = new ArrayList<Role>();
#Column
#NotNull
private Boolean locked;
...
}
Here is my Role entity:
#Entity
#Table(name="roles")
public class Role implements IBaseEntity<Role> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long roleId;
#Column(unique = true)
#NotNull
private String name;
...
}
Here is my User service:
package org.quickloanconnect.service;
public interface IUsersService extends IBaseService<User>{
public void updateUserRolesById(List<Role> roles, Long userId);
...
}
Here is the UserServiceImpl :
#Service
#Transactional
public class UsersServiceImpl extends AbstractServiceImpl<User> implements
IUsersService {
...
#Override
#Transactional
public void updateUserRolesById(List<Role> roles, Long user_id) {
userDao.updateUserRolesById(roles, user_id);
}
...
}
And here is the dao:
public interface IUsersDao {
...
#Modifying
#Query("UPDATE User u SET u.roles = :roles WHERE u.userId = :userId")
public void updateUserRolesById(#Param("roles") List<Role> roles,
#Param("userId") Long userId);
...
}
When I run this update, I get the following: SqlExceptionHelper : No value specified for parameter 2 . What is causing this? When I update my user with a single role, I see that a List of size one is getting to the dao with the correct userId (both parameters present), but the update seems to fail at the dao level with the "SqlExceptionHelper : No value specified for parameter 2" error message.

Related

ORM: EclipseLink AssociationOverride "Persistent type of override attribute cannot be resolved"

I am building an application that has a database of students, courses, and it also keeps track of all the courses that each student is taking,
I have an entity for Course and Student, and they have a one to many relationship with entity StudentCourses and an embeddable class of StudentCoursesID.
In the StudentCourse when I try to use the annotation AssociationOverride it gives me a problem saying
"Persistent type of override attribute "student" cannot be resolved"
"Persistent type of override attribute "course" cannot be resolved"
and
"Embedded ID class should not contain relationship mappings"
I dont understand if i did the mapping wrong or if there is a disconnection between my entities and classes.
Below I have each of the the entity starting with StudentCourses which is giving me issues.
StudentCourses
package jpa.entitymodels;
import javax.persistence.*;
#Entity
#Table(name = "student_courses")
#AssociationOverrides({
#AssociationOverride(name = "student", joinColumns = #JoinColumn(name = "sEmail")),
#AssociationOverride(name = "course", joinColumns = #JoinColumn(name = "cId"))
})
public class StudentCourses {
private StudentCoursesId id = new StudentCoursesId();
public StudentCourses() {
}
public StudentCourses(StudentCoursesId id) {
this.id = id;
}
#EmbeddedId
public StudentCoursesId getId() {
return id;
}
StudentCoursesId
package jpa.entitymodels;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;
import java.io.Serializable;
#Embeddable
public class StudentCoursesId implements Serializable {
private static final long serialVersionUID = 1L;
private Student student;
private Course course;
public StudentCoursesId() {
}
#ManyToOne
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
#ManyToOne
public Course getCourse() {
return course;
}
Course
package jpa.entitymodels;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "course")
public class Course {
#Id
#Column(name = "id")
int cId;
#Column(name = "name")
String cName;
#Column(name = "instructor")
String cInstructorName;
#OneToMany(mappedBy = "id.course", fetch = FetchType.LAZY)
List<StudentCourses> studentCourses = new ArrayList<>();
Student
package jpa.entitymodels;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
#Entity
#Table(name="student")
public class Student {
#Id
#Column(name = "email")
String sEmail;
#Column(name = "name")
String sName;
#Column(name = "password")
String sPass;
#OneToMany(mappedBy = "id.student", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<StudentCourses> studentCourses = new ArrayList<>();
The 'student' doesn't exist in StudentCourses which is why you get the error. Overrides you want to apply to the embeddable need to be defined on the embeddable mapping, not the StudentCourses class.
#Entity
#Table(name = "student_courses")
public class StudentCourses {
#Embedded
#AttributesOverride({
#AttributeOverride(name = "student", joinColumns = #JoinColumn(name = "sEmail")),
#AttributeOverride(nname = "course", joinColumns = #JoinColumn(name = "cId"))})
private EmbeddableClass embeddableClass;
public StudentCourses() {
}
}
JPA requires an ID class that has the simple pk types within it (or other nested composite PK classes, not relationships), requiring StudentCoursesId have a int/string property for the cId and sEmail. If you want to have mappings to course/student, maybe see the mapsId annotation or alternatively, I would map it like this:
#Entity
#Table(name = "student_courses")
#IdClass(StudentCoursesId.class)
public class StudentCourses {
#Id
#JoinColumn(name = "sEmail")
Student student;
#Id
#JoinColumn(name = "cId")
Course course;
}
public class StudentCoursesId implements Serializable {
private static final long serialVersionUID = 1L;
private String student;//Name matches id property in StudentCourses
private int course;
}

Join Table with extra column

In my spring boot application I have user model, type model and user_type. Here a join table is created in the user model as user_type.
Model in maven project with jpa :
package com.example.pharmanic.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
#Entity
#Table( name = "users",
uniqueConstraints = {
#UniqueConstraint(columnNames = "username"),
#UniqueConstraint(columnNames = "email")
})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Size(max = 20)
private String username;
#NotBlank
#Size(max = 50)
#Email
private String email;
#NotBlank
#Size(max = 120)
private String password;
**#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id") ,
inverseJoinColumns = #JoinColumn(name = "role_id")
)**
private Set<Role> roles = new HashSet<>();
public User() {
}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
The join table user_role has two columns; user_id & role_id.
I want to add an extra column to user_role table to save more data relevant to user_role. A type String column should be added to the user_role table.

Making SQL/JPQL query to select all topics that matches both keywords

Challenge:
I want to create a query that selects Topics that match both the keyword ID´s "Java" and "sql", the Topic with ID = 1 matches both keywords "Java" and "Sql.
I have implemented two simple entities Topic and Keyword. They have a bidirectional ManyToMany relationship:
#Entity
#Table(name = "Topic")
public class Topic implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "topicID")
private Long id;
#Column(name = "topicTitle")
private String title = "";
#ManyToMany
#JoinTable(name = "Join_Topic_Keyword",
joinColumns = #JoinColumn(name = "Topic_ID"),
inverseJoinColumns = #JoinColumn(name = "Keyword_ID"))
private Set<Keyword> keywords;
}
#Entity
#Table(name = "Keyword")
public class Keyword implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "keywordID")
private String id;
#ManyToMany(mappedBy = "keywords")
private Set<Topic> topics;
}
Here is the structure table.
And This is the result from Join_Topic_Keyword

Spring Data -- Query JOIN Validation ERROR -- Validation failed for query for method

I'm trying to do a 3 table Join Query with Spring data and I'm running into a query validation issue.
The exact error I get is:
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.somethinng.domain.subscriberCategoriesRepository.findByJoin()!
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92)
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62)
at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:72)
at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:53)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:144)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:212)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:77)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
... 39 more
On the Database side here are my three tables
create table subscribers(
id int auto_increment primary key,
email varchar(255),
unique (email));
create table categories (
id int auto_increment primary key,
source varchar(255) not null,
description varchar(255) not null);
create table subscriberCategories(
subscriber int not null,
source int not null,
primary key (subscriber,source), -- prevents dupes
constraint `fk_2user` foreign key (subscriber) references subscribers(id));
And here are my POJO's and Repositories
Subscribers
#Entity
#Getter
#Setter
public class Subscribers {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
private String email;
public Subscribers() { }
public Subscribers(Integer id) {
this.id = id;
}
public Subscribers(String email, String description) {
this.email = email;
}
}
Categories
#Entity
#Getter
#Setter
public class Categories {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
private String description;
#NotNull
private String source;
public Categories() { }
public Categories(Integer id) {
this.id = id;
}
public Categories(String source, String description) {
this.source = source;
this.description = description;
}
}
SubscriberCategories
#Entity
#Getter
#Setter
public class subscriberCategories {
#Id
#Column(name = "subscriber")
private Integer id;
#NotNull
private Integer source;
public subscriberCategories() {
}
public subscriberCategories(Integer subscriberId) {
this.id = subscriberId;
}
public subscriberCategories(Integer source, Integer subscriberId) {
this.source = source;
this.id = subscriberId;
}
}
Repositories
SubscriberRepository
#Repository
public interface SubscriberRepository extends CrudRepository<Subscribers, Integer> {
}
CategoriesRepository
#Repository
public interface CategoriesRepository extends CrudRepository<Categories, Integer> {
List<Categories> findById(Integer id);
Long deleteBySource(String source);
List<Categories> findBySource(String source);
}
subscriberCategoriesRepository
#Transactional
#Repository
public interface subscriberCategoriesRepository extends CrudRepository<subscriberCategories, Integer> {
#Query(value = "SELECT DISTINCT s.email as Subscriber, c.source as Source from Subscribers s" +
"Inner Join subscriberCategories sc on s.id = sc.subscriber" +
"Inner Join Categories c on sc.subscriber = s.id where s.email = 'xxxxx#gmail.com'")
List<subscriberCategories> findByJoin();
Lastly I have the following unit test which is throwing the error when I run it
#RunWith(SpringRunner.class)
#SpringBootTest
#EnableJpaRepositories(basePackageClasses = subscriberCategories.class)
#Transactional
public class subscriberCategoriesTest {
#Autowired
subscriberCategoriesRepository subscriberCategoriesRepository;
#Test
public void testLoadCategories() {
List<subscriberCategories> subscriberCategories = (List<subscriberCategories>) subscriberCategoriesRepository.findByJoin();
assertEquals("Should contain something", 1, subscriberCategories.size());
}
If someone give me a hand with this I would really appreciate it
Thanks

JPA : Implicit find by composite primary key

Please I'm trying to find Quiz by Audit (using spring data jpa) and there must be an implicit search for the quizSubCategory which has a composite key, here are the classes :
Quiz entity:
#Entity
#Table(name = "quiz")
public class Quiz {
#EmbeddedId
private QuizCK id;
#Column
private String title;
#Column
private String status;
#Column
private String state;
#Column(name = "start_date")
private Date startDate;
#Column(name = "end_date")
private Date endDate;
#Column
private String reference;
#Column
private String results;
#Column(name = "is_default")
private boolean isDefault;
#ManyToOne
#JoinColumn(name = "id_audit")
private Audit audit;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "id_quiz_sub_category", insertable = false, updatable = false),
#JoinColumn(name = "id_language", insertable = false, updatable = false)
})
private QuizSubCategory quizSubCategory;
#MapsId("idLanguage")
#ManyToOne
#JoinColumn(name="id_language", insertable = false, updatable = false)
private Language language;
public Quiz() {
}
// constructor & getters & setters
}
QuizSubCategory entity:
Entity
#Table(name = "quiz_sub_category")
public class QuizSubCategory implements Serializable {
#EmbeddedId
private QuizSubCategoryCK id;
private String libelle;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "id_quiz_category", insertable = false, updatable = false),
#JoinColumn(name = "id_language", insertable = false, updatable = false)
})
private QuizCategory quizCategory;
#MapsId("idLanguage")
#ManyToOne
#JoinColumn(name="id_language", insertable = false, updatable = false)
private Language language;
public QuizSubCategory() {
super();
}
//constructor & getters & setters
}
QuizSubCategoryCK (primary key):
#Embeddable
public class QuizSubCategoryCK implements Serializable {
#Column(name = "id_quiz_sub_category", insertable = false, updatable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private int idQuizSubCategory;
#Column(name = "id_language", insertable = false, updatable = false)
private int idLanguage;
public QuizSubCategoryCK() {
}
public int getIdQuizSubCategory() {
return idQuizSubCategory;
}
public void setIdQuizSubCategory(int idQuizSubCategory) {
this.idQuizSubCategory = idQuizSubCategory;
}
public int getIdLanguage() {
return idLanguage;
}
public void setIdLanguage(int idLanguage) {
this.idLanguage = idLanguage;
}
}
QuizRepository :
public interface QuizRepository extends JpaRepository<Quiz,QuizCK> {
List<Quiz> findByAuditAndLanguage(Audit audit, Language language);
}
Controller:
#RequestMapping(value = "/quizzes/{auditId}", method = RequestMethod.GET)
public List<QuizBean> listQuizzes(#PathVariable int auditId){
AuditBean auditBean = auditService.getAudit(auditId);
LanguageBean languageBean = languageService.getLanguageById(1);
List<QuizBean> quizzes = quizService.findByAudit(AuditMapper.fromBean(auditBean),LanguageMapper.fromBean(languageBean));
return quizzes;
}
I'm getting the following error :
Unable to find jpa.entity.QuizSubCategory with id jpa.entity.QuizSubCategoryCK#79a59c48; nested exception is javax.persistence.EntityNotFoundException: Unable to find jpa.entity.QuizSubCategory with id jpa.entity.QuizSubCategoryCK#79a59c48
Any hints please ?!