I added below mentioned custom entity for insert image from broadleaf admin console. But that image field not appear in the admin console. I added 'MEDIA' filed in my entity class. Please help me to solve this issue.
#Entity
#Table(name="MY_CUSTOM_CLASS")
#Inheritance(strategy = InheritanceType.JOINED)
#AdminPresentationClass(friendlyName = "MyCustomClass")
public class MyCustomClass implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator = "MyCustomClassId")
#GenericGenerator(
name="MyCustomClassId",
strategy="org.broadleafcommerce.common.persistence.IdOverrideTableGenerator",
parameters = {
#Parameter(name="segment_value", value="MyCustomClass"),
#Parameter(name="entity_name", value="com.community.core.domain.MyCustomClass")
}
)
#Column(name = "MY_CUSTOM_CLASS_ID")
protected Long id;
#Column(name = "NAME", nullable = false)
#AdminPresentation(friendlyName = "MyCustomClass_name", order = 1,
prominent = true, gridOrder = 1)
protected String name;
#ManyToOne(targetEntity = MediaImpl.class, cascade = {CascadeType.ALL})
#JoinColumn(name = "MEDIA_ID")
#ClonePolicy
protected Media media;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Media getMedia() {
return media;
}
public void setMedia(Media media) {
this.media = media;
}
}
Any help or workarounds are really appricated.
Put an #AdminPresentation annotation on the media field.
Related
I'm using Spring Boot,REST and JPA to build my application. In app, there are 2 entities with one to many relationship.
Entity 1 :
#Entity
#Table( name = "report")
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomReport {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "REPORT_SEQ")
#SequenceGenerator(sequenceName = "REPORT_SEQ", allocationSize = 1, name = "REPORT_SEQ")
private Long id;
private String name;
private Long createdBy;
private Timestamp lastModifiedTimestamp;
#OneToMany(mappedBy = "customReport", cascade = CascadeType.ALL)
private Set<CustomReportActivity> customReportActivitySet;
public Set<CustomReportActivity> getCustomReportActivitySet() {
return customReportActivitySet;
}
public void setCustomReportActivitySet(Set<CustomReportActivity> customReportActivitySet) {
this.customReportActivitySet = customReportActivitySet;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Timestamp getLastModifiedTimestamp() {
return lastModifiedTimestamp;
}
public void setLastModifiedTimestamp(Timestamp lastModifiedTimestamp) {
this.lastModifiedTimestamp = lastModifiedTimestamp;
}
}
Entity 2:
#Entity
#Table( name = "report_activity")
public class CustomReportActivity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "REPORT_ACTIVITY_SEQ")
#SequenceGenerator(sequenceName = "REPORT_ACTIVITY_SEQ", allocationSize = 1, name = "REPORT_ACTIVITY_SEQ")
private Long id;
String activityName;
#ManyToOne
#JoinColumn( name="report_id" )
#JsonBackReference
private CustomReport customReport;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getActivityName() {
return activityName;
}
public void setActivityName(String activityName) {
this.activityName = activityName;
}
public CustomReport getCustomReport() {
return customReport;
}
public void setCustomReport(CustomReport customReport) {
this.customReport = customReport;
}
}
And my request JSON is as follows :
{
"name": "test report",
"createdBy" : 129,
"customReportActivitySet": [
{"activityName":"a"},
{"activityName":"b"},
{"activityName":"c"},
{"activityName":"d"},
{"activityName":"e"}
]
}
I want to save both entities in one shot. I've implemented the save functionality in following way:
#RequestMapping(value="/save", method = RequestMethod.POST)
public ResponseEntity<?> addReport(#RequestBody CustomReport customReport) {
return new ResponseEntity<>(customReportService.createCustomReport(customReport), HttpStatus.CREATED);
}
CustomReportService method:
public CustomReport createCustomReport(CustomReport customReport) {
return customReportRepository.save(customReport);
}
CustomRepository:
public interface CustomReportRepository extends CrudRepository<CustomReport, Long> {
}
But I'm getting the constraint violation exception with this:
java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot
insert NULL into ("REPORT_ACTIVITY"."REPORT_ID")
Is it possible to save both entities in one save operation?
Please help!
You would have to add a small piece of code which would populate each CustomReportActivity within the CustomReport instance. Only then the persistence provide can successfully perform the cascade save operation:
public CustomReport createCustomReport(CustomReport customReport) {
customReport.getCustomReportActivitySet.forEach((activity) -> {
activity.setCustomReport(customReport);
});
return customReportRepository.save(customReport);
}
The bottom line is that the dependencies have to be set on both sides of the relationship.
Try this sample, in my case it worked as expected, child entities are saved automatically in a single save operation with creating relations to the parent entity:
#Entity
public class Parent {
#Id
private Long id;
#JoinColumn(name = "parentId")
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Child> children;
}
#Entity
public class Child {
#Id
private Long id;
private Long parentId;
}
Modelling my SpringBoot application, using Hibernate and PostgreSQL as database.
Need help to properly establish relation ManyToMany.
Class News:
#Entity(name = "news")
public class News implements Serializable {
private Long id;
private Date date;
private String text;
private String author;
private Set<HashTag> hashTags = new HashSet<HashTag>(0);
private byte[] image;
public News() {
}
public News(Date date, String text, String author, Set<HashTag> hashTags, byte[] image) {
this.date = date;
this.text = text;
this.author = author;
this.hashTags = hashTags;
this.image = image;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "news_id")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern = "DD/MM/YYYY")
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#Lob
#Type(type = "org.hibernate.type.TextType")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "news_hashTag",
joinColumns = #JoinColumn(name = "news_id"),
inverseJoinColumns = #JoinColumn(name = "hashtag_id"))
public Set<HashTag> getHashTags() {
return hashTags;
}
public void setHashTags(Set<HashTag> hashTags) {
this.hashTags = hashTags;
}
#Lob
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
And class HashTag:
#Entity(name = "hashTag")
public class HashTag implements Serializable {
private Long id;
private String name;
private String description;
private Set<News> news = new HashSet<News>(0);
public HashTag() {
}
public HashTag(String name, String description) {
this.name = name;
this.description = description;
}
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "hashtag_id")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "hashTags")
public Set<News> getNews() {
return news;
}
public void setNews(Set<News> news) {
this.news = news;
}
When I try save news like this:
Set<HashTag> hashTags = new HashSet<>();
hashTags.add(new HashTag("HashTag 1");
hashTags.add(new HashTag("HashTag 2");
News news = new News();
news.text = "Some text";
news.author = "Some author";
news.date = new Date();
news.hashTags = hashTags;
newsService.save(news);
I'm getting error:
ERROR: null value in column "news_id" violates not-null constraint
Lets see what we have:
On the owning side of the n-m relation:
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "news_hashTag",
joinColumns = #JoinColumn(name = "news_id"),
inverseJoinColumns = #JoinColumn(name = "hashtag_id"))
public Set<HashTag> getHashTags() {
return hashTags;
}
You do not provide the exclusion of null values because documentation specifies:
boolean nullable() default true;
This is wrong for the relationtable as well as the id. You must:
Set the ID to nullable=false.
Set all JoinColumns of the JoinTable to nullable=false.
There is another problem: You make a insert and an update by newsService.save(news);, you specify a Generator for the ID but have no Generator, this is ok in other databases who provide something like a nextval in Oracle. In PostGreSQL you really should use a sequence-field like this:
#Id
#Column(name = "hashtag_id", nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HashTagIDGenerator")
#SequenceGenerator(name = "HashTagIDGenerator", sequenceName = "SEQ_HASHTAG_ID")
Have a good time.
There are 3 tables. There is the variable of "relatedCameraSet" need to order by "camera.name" using SQL, but the field of "camera.name" is not in table of "RelatedCamera", is in the outer joined table of "Camera". The following annotation of #OrderBy doesn't work.
#Entity
#Table(name = "MICRO_MAP")
public class MicroMap { //main table
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private Long id;
#Column(name = "NAME", length = 32, nullable = false)
private String name;
#OneToMany(mappedBy="mapId",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#OrderBy("camera.name") //OrderBy the field of "name" in Camera table
private Set<RelatedCamera> relatedCameraSet;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<RelatedCamera> getRelatedCameraSet() {
return relatedCameraSet;
}
public void setRelatedCameraSet(Set<RelatedCamera> relatedCameraSet) {
this.relatedCameraSet = relatedCameraSet;
}
}
#Entity
#Table(name = "RELATED_CAMERA")
public class RelatedCamera {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private Long id;
#Column(name = "MAP_ID")
private String mapId;
#ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name = "CAMERA_ID", referencedColumnName="id",nullable = true)
private Camera camera;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMapId() {
return mapId;
}
public void setMapId(String mapId) {
this.mapId = mapId;
}
public Camera getCamera() {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
}
#Entity
#Table(name = "CAMERA")
public class Camera {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
How to write #OrderBy annotation in order to sort collection by camera name using SQL?
Thanks alot!
I researched your problem and found that from the API docs:
Hibernate JPA 2.1 API
The property or field name must correspond to that of a persistent property or field of the associated class or embedded class within it.
that's why it is not possible do it by just OrderBy, you can order only by camera_id column from MicroMap class.
What you want can be done by #Sort and implementing Comparable interface or by specifying a Comparator:
Annotation Type Sort
Now i realize it's impossible to do by #OrderBy, and i think it's not efficient to to do by implementing Comparable interface or specifying a Comparator, because it will take two steps to get job done, the step one is query from DB, the step two is sorting in memory. It's efficient to get sorted collection just by SQL.
In order to get high efficiency, i have to change the class of MicroMap as following:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "MICRO_MAP")
public class MicroMap {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private Long id;
#Column(name = "NAME", length = 32, nullable = false)
private String name;
// #OneToMany(mappedBy="mapId",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
// #OrderBy("camera.name") //OrderBy the field of "name" in Camera table, But JPA doesn't support
// private Set<RelatedCamera> relatedCameraSet;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and add a method in DAO or Service class.
public List<RelatedCamera> getRelatedCamera(Long mapId) {
Session session = sessionFactory.getCurrentSession();
List<RelatedCamera> list = session.createQuery(" from RelatedCamera where mapId="+mapId+" order by camera.name").list();
return list;
}
Here is my entitiy:
#Entity
#Table(name = "remind")
public class Remind {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private long id;
#Column(name = "title", nullable = false, length = 50)
private String title;
#Column(name = "remind_date", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date remindDate;
public Remind() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getRemindDate() {
return remindDate;
}
public void setRemindDate(Date remindDate) {
this.remindDate = remindDate;
}
//---Dependency---->
#OneToOne(optional = false)
#JoinColumn(name="id_user", unique = true, nullable = true, updatable = false)
private Users user;
public void setUser(Users user) {
this.user = user;
}
public Users getUser() {
return user;
}
}
And here is another entity:
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private long id;
#Column(name = "name", nullable = false, length = 50)
private String name;
public Users() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String title) {
this.name = name;
}
//---Dependency---->
#OneToOne(optional = false, mappedBy="user")
public Remind remind;
public Remind getRemind() {
return remind;
}
public void setRemind(Remind remind) {
this.remind = remind;
}
Here is diagram that Idea shows me:
But when I use in RemindController.class:
#RequestMapping(value = "/get", method = RequestMethod.GET)
#ResponseBody
public List<Remind> getReminder() {
List<Remind> list = remindRepository.findAll();
return list;
}
I have this result... infinity loop:
What am I do wrong? It seems like diagram is ok. Help me please(
It's not jpa problem. It's a problem with serializing your entity to json. You need to explicitly mark the relation as bidirectional so the serializer can skip one end.
For Spring I'm assuming you're using jackson.
Take a look at answers to this question.
I have two pojo classes wihch are named Document and DocumentUser. DocumentUser has an property documentId which linked to Document's id by foreign key.
So i want to create criteria query which retrieve Documents with its DocumentUser which is linked itself by forein key("document_id")
pojo classes:
Document
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#Entity
#Table(name = "DYS_BYS_DOSYA")
#Audited
public class Document implements Serializable {
private Long id;
private String name;
private List<DocumentUser> documentUserList = new ArrayList<DocumentUser>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID", nullable = false, precision = 15, scale = 0)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "AD", nullable = false, length = 500)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "document", fetch = FetchType.EAGER)
#Fetch(FetchMode.SUBSELECT)
#Cascade(CascadeType.ALL)
public List<DocumentUser> getDocumentUserList() {
return documentUserList;
}
public void setDocumentUserList(List<DocumentUser> documentUserList) {
this.documentUserList = documentUserList;
}
#Override
public String toString() {
return "tr.com.enlil.dys.server.servis.model.Document[id=" + id + "]";
}
}
DocumentUser:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#Entity
#Table(name = "DYS_DOSYA_SAHIBI_USER")
#Audited
public class DocumentUser implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6393919788296838129L;
private Long id;
private Long personelId;
private Document document;
private String personelName;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID", unique = true, nullable = false, precision = 15, scale = 0)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "OLUSTURUCU_PERSONEL_ID")
public Long getPersonelId() {
return personelId;
}
public void setPersonelId(Long personelId) {
this.personelId = personelId;
}
#Column(name = "KULLANICI_AD")
public String getPersonelName() {
return personelName;
}
public void setPersonelName(String personelName) {
this.personelName = personelName;
}
#ManyToOne
#JoinColumn(name = "DOSYA_ID")
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
}
In this way, how can i get Document data depends on personelId of DocumentUser table by using criteria query? I am not familiar with hibernate and i need your helps. I try to write some codes but didn't work.
public List<Document> fetchRecordsByCriteriaLimitedList(String userId) throws Exception{
Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Dosya.class);
DetachedCriteria dosyaSahibiCriteria = (DetachedCriteria) criteria.createCriteria("documentUserList");
dosyaSahibiCriteria.add(Restrictions.eq("personelId", userId));
dosyaSahibiCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return criteria.list();
}
Several problems with your code. First of all, you said
2)DocumentUser is subclass of Document
This isn't true, judging from your code (it would mean that DocumentUser extends Document), but you probably meant they are in a parent -> child relation. Second, in documentUserList mapping, there is this #OneToMany(mappedBy = "dosya", fetch = FetchType.EAGER), which means there is a field named dosya in DocumentUser, and there isn't. Instead, replace it with mappedBy = "document". Assuming everything else is ok, query to get all documents based on their DocumentUser's id would be
public List<Document> fetchRecordsByCriteriaLimitedList(String userId) throws Exception{
Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(Document.class);
criteria.createAlias("documentUserList", "users").add(Restrictions.eq("users.personelId", userId));
return criteria.list();
}