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

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

Related

How can I use post method data in back end to save many to many relationship data with #JsonIgnore annotation.My joining table is not updating

How can I use the data send through post method, and save those data in a many to many relationship? I used #JsonIgnore annotation to stop the recursion.
I have implemented two entities.One is Employee and the other is Skills.In the Employee entity I used #JsonIgnore annotation to avoid the reccursion. But when I inserted the values Employee table got updated but the joining tabled is not updating.
This is my Employee entity class
#Entity
#Table(name = "Employee")
public class Employee implements Serializable{
private static final long serialVersionUID = -3009157732242241606L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long emp_id;
#Column(name = "emp_fname")
private String emp_fname;
#Column(name = "emp_lname")
private String emp_lname;
#Column(name = "emp_email")
private String emp_email;
#Column(name = "emp_dob")
private Date emp_dob;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "emp_skills",
joinColumns = #JoinColumn(name = "emp_id", referencedColumnName = "emp_id"),
inverseJoinColumns = #JoinColumn(name = "s_id",referencedColumnName = "s_id"))
#JsonIgnore
private Set<Skills> skills;
}
This is my Skills class
#Entity
#Table(name = "Skills")
public class Skills implements Serializable {
private static final long serialVersionUID = -3009157732242241606L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long s_id;
#Column(name = "s_name")
private String s_name;
#ManyToMany(mappedBy = "skills")
private Set<Employee> employees;
And this is my controller class method to save data
#RequestMapping("/save")
#PostMapping("/save")
#CrossOrigin
public void createEmployee(#RequestBody Employee employee, BindingResult bindingResult){
Employee emp = new Employee(employee.getEmp_fname(),employee.getEmp_lname(),employee.getEmp_email(),employee.getEmp_dob());
emp.setSkills(employee.getSkills());
empRepository.save(emp);
//empRepository.save(new Employee(employee.getEmp_fname(),employee.getEmp_lname(),employee.getEmp_email(),employee.getEmp_dob()));
}
I want to update both Employee and emp_skills (the joining table) when the save method is triggered.

Hibernate multiple subqueries with DetachedCriteria

I would like write this query into HQL :
select DISTINCT * from transportation transp
inner join price p on p.transportationId = transp.transportationId
where p.sectionId = ( select sec.sectionId from section sec where sec.lineId = ( select l.lineId from line l where l.lineId = 1000000000) )
But don't know write subqueries. I know I must use DetachedCriteria.
An other question:
If we can write this query in native query (using createSQLQuery), how can cast returned objet to Transportation entity ?
Thanks
My entities :
#Entity
#Table(name = "transportation")
public class Transportation implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "transportationId")
private Integer id;
#OneToMany(mappedBy = "transportation", fetch = FetchType.EAGER)
#JsonBackReference(value = "price-transportation")
private Set<Price> prices = new HashSet<Price>();
...
}
#Entity
#Table(name = "price")
public class Price implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "priceId")
private Integer id;
#ManyToOne(optional = false)
#JoinColumn(name = "transportationId")
#JsonManagedReference(value = "price-transportation")
private Transportation transportation;
...
}
#Entity
#Table(name = "section")
public class Section implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sectionId")
private Integer id;
#ManyToOne(optional = false)
#JoinColumn(name = "lineId")
#JsonManagedReference
private Line line;
...
}
#Entity
#Table(name = "line")
public class Line implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "lineId")
private Integer id;
#OneToMany(mappedBy = "line", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JsonBackReference
private Set<Section> sections = new HashSet<Section>();
...
}
I solved my issue by using .addEntity(Transportation.class) like this :
String query = "select DISTINCT * from moyen_transport transp"
+ " join prix_voyage p on p.ID_MoyenTransport = transp.ID_MoyenTransport"
+ " where p.ID_Troncon = ( select t.ID_Troncon from troncon t where t.ID_Troncon = ( select l.ID_Ligne from ligne l where l.ID_Ligne = 1000000000) )";
Query result = getSession().createSQLQuery(query).addEntity(Transportation.class)**;
List<Transportation> results = result.list();

org.hibernate.MappingException: Foreign key must have same number of columns as the referenced primary

I have two tables
#Entity
#Table(name = "publicSitePortfolioWorks")
public class PublicSitePortfolioWorks implements java.io.Serializable {
#Id
#Column(name = "id")
private Integer id;
#Column(name = "mainImage")
private FrameworkFiles frameworkFilesByMainImage;
#Column(name = "androidImage")
private FrameworkFiles frameworkFilesByAndroidImage;
#Column(name = "bigImage")
private FrameworkFiles frameworkFilesByBigImage;
#Column(name = "mainName")
private String mainName;
#Column(name = "androidName")
private String androidName;
#Column(name = "url")
private String url;
#Column(name = "shortText")
private String shortText;
#Column(name = "`fullText`")
private String fullText;
#Column(name = "linkedObjectNameLocal")
private String linkedObjectNameLocal;
#Column(name = "`sort`")
private Integer sort;
#Column(name = "active")
private Integer active;
#OneToMany
#JoinTable(
name = "framework_files",
joinColumns = {
#JoinColumn(
// table = "framework_files",
name = "linkedObjectName",
referencedColumnName = "linkedObjectNameLocal"),
#JoinColumn(
// table = "framework_files",
name = "linkedObjectId",
referencedColumnName = "id"
)
}
// , inverseJoinColumns = #JoinColumn(name = "linkedObjectName")
)
private Set<FrameworkFiles> filesLocal = new HashSet<FrameworkFiles>(0);
And second table
#Entity
#Table(name = "framework_files")
public class FrameworkFiles implements java.io.Serializable {
#Id
#Column(name = "id")
private Integer id;
#Column(name = "fileName")
private String fileName;
#Column(name = "fileSize")
private Float fileSize;
#Column(name = "filePath")
private String filePath;
#Column(name = "fileUrl")
private String fileUrl;
#Column(name = "linkedObjectId")
private Integer linkedObjectId;
#Column(name = "linkedObjectName")
private String linkedObjectName;
#Column(name = "active")
private Integer active;
#Column(name = "uploadDate")
private Date uploadDate;
#Column(name = "uploadersIP")
private String uploadersIp;
#Column(name = "uploadersIPXFORWARDEDFOR")
private String uploadersIpxforwardedfor;
#Column(name = "userName")
private String userName;
When I have started my application, I got exception:
Caused by: org.hibernate.MappingException: Foreign key (FK_hksv6kkf3cysf5ug30q575tg1:framework_files [filesLocal_id])) must have same number of columns as the referenced primary key (framework_files [linkedObjectName,linkedObjectId,filesLocal_id])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:110)
Please advice, how to fix this exception.
I have seen many topics on stackoverflow about this Exception, but I can't understand, how to fix this error in my code.

Hibernate - Join query

I have two classes:
#Entity
public class Tick {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = false)
#JoinColumn(name = "elitesystem_id", referencedColumnName = "id")
private EliteSystem eliteSystem;
private Date createDate;
#ManyToOne(optional = true)
#JoinColumn(name = "commander_id", referencedColumnName = "id")
private Commander commander;
private String address;
and
#Entity
public class Note {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne(optional = true)
#JoinColumn(name = "tick_id", referencedColumnName = "id")
private Tick tick;
private String text;
private Date createDate;
I want to select all ticks and get notes if there are any:
Query query = session.createQuery("select t, n from Note n right join n.tick t where t.commander.name = '123'");
List<Object[]> list = query.list();
This returns only Tick objects. What is the correct approach to get the Note information as well in 1 single query?
I could put a reference to a Note into the Tick class, but this doesnt sound right, as there are only a few notes, so the column in the Tick table would mostly be empty.
Create a New class for example:
public class TickNote {
private Tick tick;
private Note note;
public TickNote(Tick tick,Note note){
this.tick=tick;
this.note=note;
Then your query is:
Query query = session.createQuery("select NEW TickNote(t, n) from Note n right join n.tick t where t.commander.name = '123'");
List<TickNote> list = query.list();

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?