Jpa one to many using join table - mysql

I have a room entity, a rule entity and an amenities entity. What i want to do is have the rule and the amenities entity filled manually beforehand and when i insert a room, i want depending on what rules and amenities the user chose to map the two in two join tables, room_rules and room_amenities.
How am i supposed to achieve this? When i persist a new Room Entity, should it already contain the rules and the amenities? Is it going to work if the collection of those are not mapped as cascade.persist?
Or should i 1st persist the room without them and then map them to the room?
What should i do?
UPDATE
My RoomEntity:
public class RoomEntity {
#Id
#GeneratedValue(strategy= GenerationType.SEQUENCE)
#Column(name = "id", nullable =false, unique = true)
private Integer id;
#Basic
#Column(name = "title", nullable = false, length = 45)
private String title;
#Basic
#Column(name = "description", nullable = false, length = 300)
private String description;
#Basic
#Column(name = "square_meters", nullable = false)
private Integer square_meters;
#Basic
#Column(name = "overnight_price", nullable = false)
private double overnight_price;
#Basic
#Column(name = "exta_person_price", nullable = false)
private double exta_person_price;
#Basic
#Column(name = "max_people", nullable = false)
private Integer max_people;
#Basic
#Column(name = "min_overnights", nullable = false)
private Integer min_overnights;
#Basic
#Column(name = "beds", nullable = false)
private Integer beds;
#Basic
#Column(name = "bathrooms", nullable = false)
private Integer bathrooms;
#Basic
#Column(name = "bedrooms", nullable = false)
private Integer bedrooms;
#Basic
#Column(name = "transport", length = 300)
private String transport;
#Basic
#Column(name = "neightborhood", length = 300)
private String neightborhood;
#Basic
#Column(name = "house_rules", length = 200)
private String house_rules;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "room_host", referencedColumnName = "username", /*nullable = false,*/ insertable = false, updatable = false)
private HostEntity hostEntity;
public HostEntity getHostEntity() {
return hostEntity;
}
public void setHostEntity(HostEntity hostEntity) {
this.hostEntity = hostEntity;
}
#OneToOne
#JoinColumn(name = "room_type_id", referencedColumnName = "id", /*nullable = false,*/ insertable = false, updatable = false)
private TypeEntity typeEntity;
public TypeEntity getTypeEntity() {
return typeEntity;
}
public void setTypeEntity(TypeEntity typeEntity) {
this.typeEntity = typeEntity;
}
#OneToOne(cascade={CascadeType.ALL})
#JoinColumn(name = "room_location", referencedColumnName = "id"/*, nullable = false, insertable = false, updatable = false*/)
private LocationEntity locationEntity;
public LocationEntity getLocationEntity() {
return locationEntity;
}
public void setLocationEntity(LocationEntity locationEntity) {
this.locationEntity = locationEntity;
}
#OneToMany(cascade = {CascadeType.ALL})
#JoinTable(
/*name = "room_pictures",*/
joinColumns = {#JoinColumn(name = "room_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn (name ="picture_id", referencedColumnName = "id", unique = true)}
)
private Collection<PictureEntity> pictureEntities = new ArrayList<>();
public Collection<PictureEntity> getPictureEntities() {
return pictureEntities;
}
public void setPictureEntities(Collection<PictureEntity> pictureEntities) {
this.pictureEntities = pictureEntities;
}
#OneToMany
#JoinTable(
/*name = "room_amenities",*/
joinColumns = {#JoinColumn(name = "room_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn (name ="amenity_id", referencedColumnName = "id")}
)
private Collection<AmenitiesEntity> amenitiesEntities = new ArrayList<>();
public Collection<AmenitiesEntity> getAmenitiesEntities() {
return amenitiesEntities;
}
public void setAmenitiesEntities(Collection<AmenitiesEntity> amenitiesEntities) {
this.amenitiesEntities = amenitiesEntities;
}
#OneToMany
#JoinTable(
/*name = "room_amenities",*/
joinColumns = {#JoinColumn(name = "room_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn (name ="rule_id", referencedColumnName = "id")}
)
private Collection<RuleEntity> ruleEntities = new ArrayList<>();
public Collection<RuleEntity> getRuleEntities() {
return ruleEntities;
}
public void setRuleEntities(Collection<RuleEntity> ruleEntities) {
this.ruleEntities = ruleEntities;
}
public Collection<Picture> toPicturesModel(){
Collection<Picture> pictures = new ArrayList<>();
for(PictureEntity o : this.pictureEntities){
pictures.add(o.toModel());
}
return pictures;
}
public Collection<Amenities> toAmenitiesModel(){
Collection<Amenities> amenities = new ArrayList<>();
for(AmenitiesEntity o : this.amenitiesEntities){
amenities.add(o.toModel());
}
return amenities;
}
public Collection<Rule> toRulesModel(){
Collection<Rule> rules = new ArrayList<>();
for(RuleEntity o : this.ruleEntities){
rules.add(o.toModel());
}
return rules;
}
public Room toModel(Integer depth){
System.out.println("RoomEntity:::toModel()");
return new Room(
this.hostEntity == null? null : this.hostEntity.toModel(depth),
this.getTypeEntity() == null? null : this.typeEntity.toModel(),
this.getLocationEntity()== null? null : this.locationEntity.toModel(),
this.getPictureEntities() == null ? null : this.toPicturesModel(),
this.getAmenitiesEntities() == null? null : this.toAmenitiesModel(),
this.getRuleEntities() == null? null : this.toRulesModel(),
this.title, this.description, this.square_meters,
this.overnight_price, this.exta_person_price,
this.max_people, this.min_overnights, this.beds, this.bathrooms,
this.bedrooms, this.transport, this.neightborhood, this.house_rules);
}
}
My HostEntity inherits from RenterEntity the primary key username:
public class HostEntity extends RenterEntity {
#Basic
#Column(name = "about", length = 200)
private String about;
#Basic
#Column(name = "confirmed", nullable = false)
private boolean confirmed;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "hostEntity")
private Collection<RoomEntity> roomEntities;
public Collection<RoomEntity> getRoomEntities() {
return roomEntities;
}
public void setRoomEntities(Collection<RoomEntity> roomEntities) {
this.roomEntities = roomEntities;
}
My LocationEntity:
public class LocationEntity{
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
#Column(name = "id", nullable =false, unique = true)
private Integer id;
#Basic
#Column(name = "latitude", nullable = false, precision = 0)
private double latitude;
#Basic
#Column(name = "longitude", nullable = false, precision = 0)
private double longitude;
#Basic
#Column(name = "street_number", length = STREET_MAX)
private String street_number;
#Basic
#Column(name= "route", length = ROUTE_MAX)
private String route;
#Basic
#Column(name = "locality", length = LOCALITY_MAX)
private String locality;
#Basic
#Column(name = "postal_code", length = POSTAL_CODE_MAX)
private String postal_code;
#Basic
#Column(name = "country", length = COUNTRY_MAX)
private String country;
#Basic
#Column(name = "administrative_area_level_5", length = ADMINISTRATIVE_AREA_LEVEL_MAX)
private String administrative_area_level_5;
#Basic
#Column(name = "administrative_area_level_4", length = ADMINISTRATIVE_AREA_LEVEL_MAX)
private String administrative_area_level_4;
#Basic
#Column(name = "administrative_area_level_3", length = ADMINISTRATIVE_AREA_LEVEL_MAX)
private String administrative_area_level_3;
#Basic
#Column(name = "administrative_area_level_2", length = ADMINISTRATIVE_AREA_LEVEL_MAX)
private String administrative_area_level_2;
#Basic
#Column(name = "administrative_area_level_1", length = ADMINISTRATIVE_AREA_LEVEL_MAX)
private String administrative_area_level_1;
#Basic
#Column(name = "formatted_address", length = FORMATTED_ADRESS_MAX, nullable = false, unique = true)
private String formatted_address;
}
My TypeEntity:
public class TypeEntity {
#Id
#Column(name = "id", nullable = false, unique = true)
private Integer id;
#Basic
#Column(name = "type_name", nullable = false, length = 45)
private String type;
#OneToOne(mappedBy = "typeEntity")
private RoomEntity roomEntity;
}
My RuleEntity:
public class RuleEntity {
#Id
#Column(name = "id", nullable =false, unique = true)
//#GeneratedValue(strategy= GenerationType.SEQUENCE)
private Integer id;
#Basic
#Column(name = "rule", nullable =false , unique = true, length = 50)
private String rule;
}
My PictureEntity:
public class PictureEntity {
#Id
#Column(name = "id", nullable =false, unique = true)
#GeneratedValue(strategy= GenerationType.SEQUENCE)
private Integer picture_id;
#Basic
#Column(name = "thumbnail_url", nullable =false, length = 100)
private String thumbnail_url;
#Basic
#Column(name = "medium_url", nullable =false, length = 100)
private String medium_url;
#Basic
#Column(name = "picture_url", nullable =false, length = 100)
private String picture_url;
#Basic
#Column(name = "xl_picture_url", nullable =false, length = 100)
private String xl_picture_url;
}
My AmenitiesEntity:
public class AmenitiesEntity {
#Id
#Column(name = "id", nullable =false, unique = true)
//#GeneratedValue(strategy= GenerationType.SEQUENCE)
private Integer id;
#Basic
#Column(name = "name", nullable = false, unique = true, length = 50)
private String amenity;
}
My code that creates a room is this:
public Room addRoom(RoomInput room) {
dao.setParam("username", room.getOwner());
List<HostEntity> owner = dao.getTuples("users.findByUsername");
RoomEntity newRoom = new RoomEntity(room.getTitle(), room.getDescription(), room.getSquare_meters(), room.getOvernight_price(),
room.getExta_person_price(), room.getMax_people(), room.getMin_overnights(), room.getBeds(), room.getBathrooms(),
room.getBedrooms(), room.getTransport(), room.getNeightborhood(), room.getHouse_rules());
newRoom.setLocationEntity(room.getLocation().toEntity());
for(Picture o :room.getPictures()){
newRoom.getPictureEntities().add(o.toEntity());
}
RoomEntity entity = dao.insertTuple(newRoom);
entity.setHostEntity(owner.get(0));
for(Amenities o : room.getAmenities()){
entity.getAmenitiesEntities().add(o.toEntity());
}
for(Rule o : room.getRules()){
entity.getRuleEntities().add(o.toEntity());
}
entity.setTypeEntity(room.getType().toEntity());
entity = dao.updateTuple(entity);
System.out.println(entity.toString());
return (entity == null) ? null : entity.toModel(0);
}
What happens now is that, even though my 3 join tables,
room_pictures, room_rules, room_amenities get updated correctly,
the room i put in the database has the foreign key of the host(username)
and the type(id) null.
Is there a better way in doing all this? Right now i 1st persist the new room,
and cascade persist the pictures and the location and then i merge the room with the new values of host, amenities and rules updated.

UPDATE
I fixed the problem. Now i do one insert for the entities i want to persist with the room, aka location and pictures and one merge to connect the detatched entities amenities/rules in the join tables and host/type foreign keys in the room table. The problem with host and type was that i had in the #JoinColumn updateable and instertable to be false which was wrong. After i deleted those statements, it worked! My code in the end to persist/merge the detatched and new entities is this:
public Room addRoom(RoomInput room) {
dao.setParam("username", room.getOwner());
HostEntity host = null;
List<HostEntity> owner = dao.getTuples("users.findByUsername");
RoomEntity newRoom = new RoomEntity(room.getTitle(), room.getDescription(), room.getSquare_meters(), room.getOvernight_price(),
room.getExta_person_price(), room.getMax_people(), room.getMin_overnights(), room.getBeds(), room.getBathrooms(),
room.getBedrooms(), room.getTransport(), room.getNeightborhood(), room.getHouse_rules());
System.out.println(owner.get(0).toString());
newRoom.setLocationEntity(room.getLocation().toEntity());
for(Picture o :room.getPictures()){
newRoom.getPictureEntities().add(o.toEntity());
}
RoomEntity entity = dao.insertTuple(newRoom);
for(Amenities o : room.getAmenities()){
entity.getAmenitiesEntities().add(o.toEntity());
}
for(Rule o : room.getRules()){
entity.getRuleEntities().add(o.toEntity());
}
entity.setHostEntity(owner.get(0));
entity.setTypeEntity(room.getType().toEntity());
dao.updateTuple(entity);
System.out.println(entity.toString());
return (entity == null) ? null : entity.toModel(0);
}

Related

How can I select column data of table from jpaRepository of another table using #Query annotation in spring Boot?

Note: I'm Using MYSQL also ,and I tried to links the tables in WorkBench but it didn't work
Here is my RealEsateCategory.java
#Entity
#Table(name = "realestatecategory")
public class RealEstateCategory {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "auction_ID")
private int auctionID;
#Column(name = "auction_Title")
private String auctionTitle;
#Column(name = "category_Name")
private String categoryName;
#Column(name = "subcategory_Name")
private String subCategoryName;
#Column(name = "type")
private String type;
#Column(name = "number_Of_Rooms")
private int numberOfRooms;
#Column(name = "number_Of_Bathrooms")
private int numberOfBathrooms;
#Column(name = "number_Of_Floor")
private int numberOfFloor;
#Column(name = "land_Area")
private int landArea;
#Column(name = "building_Area")
private int buildingArea;
#Column(name = "building_Age")
private int buildingAge;
#Column(name = "city")
private String city;
#Column(name = "image1_URL")
private String image1URL;
#Column(name = "image2_URL")
private String image2URL;
#Column(name = "image3_URL")
private String image3URL;
#Column(name = "image4_URL")
private String image4URL;
#Column(name = "image5_URL")
private String image5URL;
#Column(name = "minimum_Price")
private double minimumPrice;
#Column(name = "current_Price")
private double currentPrice;
#Column(name = "owner_Id")
private int ownerId;
#OneToOne
#JoinColumn(name = "users_id")
private Users users;
Users.java
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "namee")
private String name;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "phone_Number")
private int phoneNumber;
#OneToOne(mappedBy = "users")
private RealEstateCategory realEstateCategory;
RealEstateCategoryRepo.java
public interface RealEstateCategoryRepo extends JpaRepository<RealEstateCategory,Long> {
#Query("select re from RealEstateCategory re where re.subCategoryName like %?1%"
+ "and re.type like %?2%"
+ "and re.city like %?3%"
+ "and re.numberOfRooms = ?4 "
+ "and re.numberOfBathrooms = ?5 "
+ "and re.numberOfFloor = ?6 "
+ "and re.landArea = ?7 "
+ "and re.buildingArea = ?8 "
+ "and re.buildingAge = ?9 "
)
List<RealEstateCategory> findAll(String subCategory,String type,String city,int noOfRoom,int noOfBathRoom,int noOfFloor,int landArea,int buildingArea,int buildingAge);
#Query("select re from RealEstateCategory re where re.auctionID = ?1 ")
List<RealEstateCategory> findAllDetails(int id);
#Query("select re.users.name from RealEstateCategory re where re.auctionID = ?1 ")
List<Users> findAllDetailsOwner(int id);
}
the Controller
#RequestMapping("/RealEstateBiddingPage")
public String getRealEstateBiddingPage(ModelMap modelMap, #RequestParam int auctionID){
modelMap.put("auctionDetails",realEstateCategoryServ.getAuctionDetails(auctionID));
modelMap.put("auctionDetailsOwner",realEstateCategoryServ.getAuctionOwner(auctionID));
return "RealEstateBiddingPage";
}
RealEstateCategoryServ.java
public List<RealEstateCategory> getAuctionDetails(int id){
return realEstateCategoryRepo.findAllDetails(id);
}
public List<Users> getAuctionOwner(int id){
return realEstateCategoryRepo.findAllDetailsOwner(id);
}
so i'm trying to fetch the data in my Jsp page , the data that i have been retrieved from
#Query("select re from RealEstateCategory re where re.auctionID = ?1 ")
its work ,,, but the data of the other query that related to the other table it doesn't work..
so help!!!!

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

could not execute statement; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

I try to insert some data by posting JSON, but I dont know why, it returns me an error saying that Field 'id_accessoire' could not be empty (null).
When I send my JSON with Advanced Rest Client, the field id_accessoire is not empty.
First, this i my entity (file Affaire.java) , with all the fields like they are in my database :
#Entity
#Data
#Table(name = "affaire")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Affaire implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", insertable = false, nullable = false)
private Integer id;
#Column(name = "sn", nullable = false)
private String sn;
#Column(name = "zc")
private String zc;
#Column(name = "certificat")
private String certificat;
#Column(name = "etat", nullable = false)
private Boolean etat;
#Column(name = "finEval", nullable = false)
private Date finEval;
#Column(name = "finRep", nullable = false)
private Date finRep;
#Column(name = "limiteCalendaire", nullable = false)
private String limiteCalendaire;
#Column(name = "date_lancement", nullable = false)
private Date dateLancement;
#Column(name = "accordClient", nullable = false)
private boolean accordClient;
#Column(name="idAccessoire", insertable = false, updatable = false)
private Integer idAccessoire;
#Column(name="idFlux", insertable = false, nullable = false, updatable = false)
private Integer idFlux;
#Column(name="idReparation", insertable = false, nullable = false, updatable = false)
private Integer idReparation;
#Column(name="idVariante", insertable = false, nullable = false, updatable = false)
private Integer idVariante;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="idAccessoire", nullable = false)
#JsonBackReference(value = "affaireAccess")
private Accessoire accessoire;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="idFlux", nullable = false)
#JsonBackReference(value = "affaireFlux")
private Flux flux;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="idReparation", nullable = false)
#JsonBackReference(value = "affaireRep")
private Reparation reparation;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="idVariante", nullable = false)
#JsonBackReference(value = "affaireVariante")
private Variante variante;
#OneToMany(mappedBy = "affaire", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
//#JsonManagedReference(value = "affecterAffaire")
#ToString.Exclude
private List<Affecter> affecters;
}
And finally, this is the JSON that I try to post, but it's not working :
{
"sn":"4444AAA",
"zc":null,
"certificat":null,
"etat" : false,
"finEval": "2019-08-25",
"finRep": "2019-09-14",
"limiteCalendaire":"10R28",
"dateLancement":"2019-07-19",
"accordClient" : false,
"idAccessoire" : 1,
"idFlux": 1,
"idReparation": 2,
"idVariante" : 7,
}
The error is that the field "id_accessoire_ could not be empty (null)
From you entity class, I can see that idAccessoire column in not insertable not updatable.
#Column(name="idAccessoire", insertable = false, updatable = false)
private Integer idAccessoire;
This means that irrespective of which value you set in code, it will be ignored.
Now, If idAccessoire is defined as not nullable field in your table configuration this error is thrown.
1) Do you really want this field to be not insertable or updatable?
2) If you must specify this column as non null in database, try to specify a default value, if it suites your business logic.

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.

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?