how to create a manytomany relationship between an entity and org.hibernate.usertype.UserType - usertype

I have an entity like this:
#Entity
#Table(name = "PLATFORM")
public class Platform{
#Id
#Column(name = "PLATFORM_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer platformId;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="PLATFORM_TYPE_ID")
private PlatformType platformType;
//must be manytomany but how?
private List<MimeType> supportedMimeTypes;
...
And I have a MimeType class which is a org.hibernate.usertype.UserType indeed.
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MimeType extends EnumarationType{
private static final long serialVersionUID = 1L;
public static final MimeType XML = new MimeType(new Integer(0), "XML");
public static final MimeType JSON = new MimeType(new Integer(1), "JSON");
protected static ArrayList<MimeType> list = new ArrayList<MimeType>();
static {
SQL_TYPES = new int[] { Types.INTEGER };
list.add(XML);
list.add(JSON);
}
public MimeType(){
}
public MimeType(Integer value, String label) {
super(value, label);
}
public List<?> getList() {
return list;
}
public static MimeType getById(int id) {
Iterator<MimeType> it = list.iterator();
while (it.hasNext()) {
MimeType status = it.next();
int statusId = Integer.parseInt(status.getValue());
if (statusId == id)
return status;
}
return null;
}
public static MimeType getByName(String name) {
Iterator<MimeType> it = list.iterator();
while (it.hasNext()) {
MimeType status = it.next();
String statusName = status.getLabel();
if (statusName.equalsIgnoreCase(name))
return status;
}
return null;
}
}
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public abstract class EnumarationTypeBase implements UserType, Serializable {
protected static int[] SQL_TYPES = { Types.VARCHAR };
protected String label;
protected Object value;
protected String resourceKey;
public EnumarationTypeBase() {
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public abstract List<?> getList();
private Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public EnumarationTypeBase resolveFromValue(Object value) {
List<?> list = getList();
if (list == null)
return null;
EnumarationTypeBase result = null;
for (Iterator<?> itr = list.iterator(); itr.hasNext();) {
EnumarationTypeBase enm = (EnumarationTypeBase) itr.next();
if (enm.getValue().toString().equals(value.toString())) {
result = enm;
break;
}
}
return result;
}
public EnumarationTypeBase resolveFromLabel(Object label) {
List<?> list = getList();
if (list == null)
return null;
EnumarationTypeBase result = null;
for (Iterator<?> itr = list.iterator(); itr.hasNext();) {
EnumarationTypeBase enm = (EnumarationTypeBase) itr.next();
if (enm.getLabel().equals(label.toString())) {
result = enm;
break;
}
}
return result;
}
public String toString() {
return getLabel();
}
public int[] sqlTypes() {
return SQL_TYPES;
}
public Class<?> returnedClass() {
return getClass();
}
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException,
SQLException {
value = resultSet.getString(names[0]);
return resultSet.wasNull() ? null : resolveFromValue(value);
}
public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException,
SQLException {
EnumarationTypeBase enumType = (EnumarationTypeBase) value;
if (value == null) {
statement.setNull(index, sqlTypes()[0]);
} else {
statement.setString(index, enumType.getValue().toString());
}
}
public boolean equals(Object x, Object y) {
if (x == y)
return true;
if (null == x || null == y)
return false;
return x.equals(y);
}
public boolean equals(Object obj) {
if (obj instanceof EnumarationTypeBase)
return this.getValue().equals(((EnumarationTypeBase) obj).getValue());
return super.equals(obj);
}
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
public Object deepCopy(Object value) {
return value;
}
public boolean isMutable() {
return false;
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public int hashCode() {
return (new Integer(this.getValue().toString())).intValue();
}
public String getResourceKey() {
if (resourceKey == null)
resourceKey = resolveFromValue(this.value).resourceKey;
return resourceKey;
}
public void setResourceKey(String resourceKey) {
this.resourceKey = resourceKey;
}
}
public abstract class EnumarationType extends EnumarationTypeBase {
protected static int[] SQL_TYPES = { Types.VARCHAR };
public EnumarationType() {
}
public EnumarationType(Integer value, String label) {
this.value = value.toString();
this.label = label;
}
public EnumarationType(String value, String label) {
this.value = value.toString();
this.label = label;
}
public EnumarationType(Integer value, String label, String resourceKey) {
this.value = value.toString();
this.label = label;
this.resourceKey = resourceKey;
}
public String getValue() {
return (String) value;
}
public BigDecimal getBigDecimalValue() {
BigDecimal tValue = new BigDecimal(getValue());
return tValue;
}
public void setValue(String value) {
this.value = value;
}
}
So how could i define a manytomany relationship between the entity Platform and non-entity usertype MimeType.
Please help.

I solved the problem. Here is the working code
...
#ElementCollection(targetClass = MimeType.class,fetch=FetchType.EAGER)
#CollectionTable(name = "PLATFORM_MIME_TYPE", joinColumns = #JoinColumn(name = "PLATFORM_ID"))
#Enumerated(EnumType.ORDINAL)
#Column(name = "MIME_TYPE_ID", columnDefinition="integer")
#Type(
type = Constants.ENUMERATION_TYPE,
parameters = {
#Parameter(
name = "enumClass",
value = "com.ba.reme.model.enums.MimeType"),
#Parameter(
name = "identifierMethod",
value = "toInt"),
#Parameter(
name = "valueOfMethod",
value = "fromInt")
}
)
private Set<MimeType> supportedMimeTypes;
...
And the MimeType enum :
public enum MimeType {
XML(1),
JSON(2),
RSS(3);
private int value;
MimeType(int value) {
this.value = value;
}
// the identifierMethod
public int toInt() {
return value;
}
// the valueOfMethod
public static MimeType fromInt(int value) {
switch(value) {
case 2: return JSON;
case 3: return RSS;
default: return XML;
}
}
public String toString() {
switch(this) {
case RSS: return "rss";
case JSON: return "json";
default: return "xml";
}
}
}

Related

How to query a many to many relationship in spring boot repository

I am trying to have the api return a list of notes, associated by a many to many relationship with labels, given a label id. Spring boot automatically created a bridge table called notes_tables with a notes_id field and a labels_id field. Spring Boot also created a notes table and a labels table. I attempted the following:
#Query(value="select * from notes join notes_labels on note.id=notes_id join labels on labels_id=labels.id where labels_id=:lid", nativeQuery=true)
public List<Note> findNotesForLabel(#Param("lid") int labelId);
I just need to get this to work but I am specifically curious if I can get it to work with jpa method query. Any query will do as long as it works though.
EDIT:
Entities
Note.java
package com.example.maapi.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "notes")
public class Note {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String note;
private String title;
private String status = "private";
#ManyToOne
#JsonIgnore
private User user;
#ManyToOne
#JsonIgnore
private Folder folder;
#ManyToMany
#JsonIgnore
private List<Label> labels;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Folder getFolder() {
return folder;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setFolder(Folder folder) {
this.folder = folder;
}
public List<Label> getLabels() {
return labels;
}
public void setLabels(List<Label> labels) {
this.labels = labels;
}
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Note)) {
return false;
}
Note note = (Note) o;
return id == note.id && Objects.equals(note, note.note) &&
Objects.equals(title, note.title) && Objects.equals(status,
note.status) && Objects.equals(user, note.user) &&
Objects.equals(folder, note.folder) && Objects.equals(labels,
note.labels);
}
#Override
public int hashCode() {
return Objects.hash(id, note, title, status, user, folder,
labels);
}
}
Label.java
package com.example.maapi.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "labels")
public class Label {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String title;
private String status = "private";
#ManyToOne
#JsonIgnore
private User user;
#ManyToOne
#JsonIgnore
private Folder folder;
#ManyToMany(mappedBy = "labels")
#JsonIgnore
private List<Note> notes;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Folder getFolder() {
return folder;
}
public void setFolder(Folder folder) {
this.folder = folder;
}
public List<Note> getNotes() {
return notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Label)) {
return false;
}
Label label = (Label) o;
return id == label.id && Objects.equals(title, label.title) &&
Objects.equals(status, label.status) && Objects.equals(user,
label.user) && Objects.equals(folder, label.folder) &&
Objects.equals(notes, label.notes);
}
#Override
public int hashCode() {
return Objects.hash(id, title, status, user, folder, notes);
}
}
Services:
NoteService.java
package com.example.maapi.services;
import com.example.maapi.models.Folder;
import com.example.maapi.models.Note;
import com.example.maapi.models.User;
import com.example.maapi.repositories.FolderRepo;
import com.example.maapi.repositories.NoteRepo;
import com.example.maapi.repositories.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class NoteService {
#Autowired
NoteRepo noteRepo;
#Autowired
UserRepo userRepo;
#Autowired
FolderRepo folderRepo;
public List<Note> findAllNotes(){
return noteRepo.findAllNotes();
}
public Note findNoteById(int noteId){
return noteRepo.findNoteById(noteId);
}
public List<Note> findNotesByUser(int userId){
return noteRepo.findNotesByUser(userId);
}
public Note createNoteForUser(int userId, Note note){
User user = userRepo.findUserById(userId);
note.setUser(user);
return noteRepo.save(note);
}
public List<Note> findNotesByFolder(int folderId){
return noteRepo.findNotesByFolder(folderId);
}
public Note createNoteForFolder(int folderId, Note note){
Folder folder = folderRepo.findFolderById(folderId);
note.setFolder(folder);
note.setUser(folder.getUser());
return noteRepo.save(note);
}
public int updateNote(int noteId, Note updatedNote){
Note note = noteRepo.findNoteById(noteId);
updatedNote.setUser(note.getUser());
updatedNote.setFolder(note.getFolder());
noteRepo.save(updatedNote);
if(updatedNote.equals(note)){
return 1;
} else {
return 0;
}
}
public int deleteNote(int noteId){
noteRepo.deleteById(noteId);
if(noteRepo.findNoteById(noteId) == null) {
return 1;
} else {
return 0;
}
}
// SEARCH IMPLEMENTATION
public List<Note> searchForNote(String note){
return noteRepo.searchForNote(note);
}
}
LabelService.java
So this is the spring-booty way to do this that I was able to figure out. CrudRepository has findById(Integer id) which returns an Optional object.
All you have to do is optional.get() to return the encapsulated object and then you can return the desired field (in my case List notes) with a getter.
// CrudRepo interface provides the findById method which returns an Optional<Label>
// object that may or may not exist. Optional.get() returns the encapsulated object.
public List<Note> findNotesByLabelId(int labelId) {
Optional<Label> label = labelRepo.findById(labelId);
return label.get().getNotes();
}
Try this one!
SELECT * FROM notes n INNER JOIN notes_labels nl ON nl.notes_id = n.note_id WHERE nl.labels_id = ?1
Edit:
#Entity
#Table(name = "notes")
#NamedNativeQuery(name = "Note.getNoteByLabel", resultSetMapping = "getNote",
query = "SELECT n.id,n.note,n.title,n.status FROM notes n INNER JOIN notes_labels nl ON nl.notes_id = n.note_id WHERE nl.labels_id = ?1")
#SqlResultSetMapping(name = "getNote", classes = #ConstructorResult(targetClass = Note.class,
columns = {#ColumnResult(name = "id", type = Integer.class),#ColumnResult(name = "note", type = String.class)
#ColumnResult(name = "title", type = String.class),#ColumnResult(name = "status", type = String.class)}))
public class Note {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String note;
private String title;
private String status = "private";
NoteRepo.java
#Query(nativeQuery = true)
List<Note> getNoteByLabel(int labelId);
Build a proper constructor and try this one.
You have to think on it as if it was simple POO. For example, you can use:
#Query("FROM Note n WHERE (SELECT l FROM Label l WHERE l.id = :lid) MEMBER OF labels")
public List<Note> findNotesByLabel(#Param("lid") int id);
which basically means,
get all notes where given id's label is part of the labels attribute
I don't fully know each implementation yet, surely the documentation would give a better approach, but I just came up with that problem and it did the trick

Exception : java.util.LinkedHashMap cannot be cast to com.excel.entity.ClassA

This is the generic method through which i am accepting list of
objects and downcasting to a specific object
public Response generate(List<?> list){
List<ClassA> List1 = new ArrayList<ClassA>();
List<ClassB> List2 = new ArrayList<ClassB>();
List<ClassC> List3 = new ArrayList<ClassC>();
if(list instanceof List<?>){
List1=(List<ClassA>) list;//in this line i am getting error
addDataToExcel(List1);
}
else if(list instanceof List<?>){
List2=(List<ClassB>) list;
addDataToExcel(List1);
}
else if(list instanceof List<?>){
List3=(List<ClassC>) list;
addDataToExcel(List1);
}
This is classA
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
#Entity
#Table(name="ClassA")
public class ClassA {
#Id
#Column(name="rollNo")
private int rollNo;
#Column(name="name")
private String name;
#Column(name="english")
private double english;
#Column(name="maths")
private double maths;
#Column(name="science")
private double science;
#Column(name="totalMarks")
private double totalMarks;
#Column(name="percentage")
private double percentage;
#Column(name="status")
private boolean status;
#Lob
#Column(name="file", columnDefinition="BLOB")
private byte[] file;
public ClassA() {
// TODO Auto-generated constructor stub
}
public ClassA(int rollNo, String name, double english, double maths, double science, double totalMarks,
double percentage, boolean status, byte[] file) {
super();
this.rollNo = rollNo;
this.name = name;
this.english = english;
this.maths = maths;
this.science = science;
this.totalMarks = totalMarks;
this.percentage = percentage;
this.status = status;
this.file = file;
}
public int getRollNo() {
return rollNo;
}
public void setRollNo(int rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getEnglish() {
return english;
}
public void setEnglish(double english) {
this.english = english;
}
public double getMaths() {
return maths;
}
public void setMaths(double maths) {
this.maths = maths;
}
public double getScience() {
return science;
}
public void setScience(double science) {
this.science = science;
}
public double getTotalMarks() {
return totalMarks;
}
public void setTotalMarks(double totalMarks) {
this.totalMarks = totalMarks;
}
public double getPercentage() {
return percentage;
}
public void setPercentage(double percentage) {
this.percentage = percentage;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public byte[] getFile() {
return file;
}
public void setFile(byte[] file) {
this.file = file;
}
}
This is the method which accepts List and generate excel
public void add(List<ClassA> classA) {
System.out.println("entering add");
String excelFilePath = "D:/eclipse_neon/StudentInfo.xlsx";
try {
FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
int rowNum = 1;
int a=2;
for(ClassA info: classA){
System.out.println("netering loop");
Row row = sheet.getRow(rowNum++);
row.createCell(2).setCellValue(info.getEnglish());
row.createCell(3).setCellValue(info.getMaths());
row.createCell(4).setCellValue(info.getScience());
row.createCell(5).setCellFormula("SUM(C"+a+","+"D"+a+","+"E"+a+")");
row.createCell(6).setCellFormula("("+"F"+a+"*"+"100"+")"+"/"+"300");
row.createCell(7).setCellValue(info.isStatus());
a++;
}
System.out.println("after for loop");
inputStream.close();
FileOutputStream outputStream = new FileOutputStream("D:/eclipse_neon/StudentInfo.xlsx");
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException
| InvalidFormatException ex) {
ex.printStackTrace();
}
}
I am not able to downcast to my specific List of class from generic list soo any suggestions are welcomed Thankyou
That's probably because you're sending a list as parameter containing a List and class A is not related to LinkedHashMap (not a subclass for example) and therefore it cannot cast. If you can provide more details what is class A and what is the list you're sending as arguments to your method.
Check https://www.baeldung.com/java-type-casting

Fetch parent-id in a bidirectional hibernate mapping

I have a spring rest application with two entities with a bidirectional relationshop (one-to-many, many to one). To overcome nested fetching issues, #JsonManagedReference/#JsonBackReference has been used for a perent/child relationship between entities.
The entites look as this:
#Entity
#Table(name = "Parent")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Parent implements java.io.Serializable {
private Integer id;
private List<Child> childList;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
#JsonManagedReference
public List<Child> getChildList() {
return childList;
}
public void setChildListe(List<Child> childListe) {
this.childList = childList;
}
}
#Entity
#Table(name = "Child")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Child implements java.io.Serializable {
private Integer id;
private Parent parent;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ParentID")
#JsonBackReference
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
This works fine when fetching the Parent element, the childset is then fetched alongside and displayed as an json-array.
However, there is no reference to parent in the child element due to the usage of jsonbackreferance.
I would like to either get the parent object attached to the child-elemens in the json response, or at least fetch the parent id, when requesting for a singlle child element through rest.
All feedback will be appriciated :)
I had a similar issue and I solved it by using custom serializer/deserializer
This is how I procedeed (please adapt it to your own code):
ChildSerializer
public class ChildSerializer extends StdSerializer<Child> {
private static final long serialVersionUID = -265706839304575646L;
public ChildSerializer(Class<Child> t) {
super(t);
}
public ChildSerializer() {
this(null);
}
#Override
public void serialize(Child child, JsonGenerator jg, SerializerProvider sp)
throws IOException, JsonGenerationException {
jg.writeStartObject();
jg.writeStringField("name", child.getName());
jg.writeStringField("surname", child.getSurname());
Parent parent = child.getParent();
jg.writeObjectFieldStart("parent");
jg.writeStringField("name", parent.getName());
jg.writeStringField("surname", parent.getSurname());
jg.writeEndObject();
}
}
Child
#JsonSerialize(using = ChildSerializer.class)
public class Child implements Serializable {
private static final long serialVersionUID = 7902561110976676934L;
private String name;
private String surname;
private Parent parent;
public Child(String name, String surname, Parent parent) {
this(name, surname);
this.parent = parent;
}
public Child(String name, String surname) {
this();
this.name = name;
this.surname = surname;
}
public Child() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((parent == null) ? 0 : parent.hashCode());
result = prime * result + ((surname == null) ? 0 : surname.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Child other = (Child) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (parent == null) {
if (other.parent != null)
return false;
} else if (!parent.equals(other.parent))
return false;
if (surname == null) {
if (other.surname != null)
return false;
} else if (!surname.equals(other.surname))
return false;
return true;
}
}
Parent
public class Parent implements Serializable {
private static final long serialVersionUID = -5604725691780073247L;
private String name;
private String surname;
private List<Child> childs;
public Parent(String name, String surname) {
this();
this.name = name;
this.surname = surname;
}
public Parent(String name, String surname, List<Child> childs) {
this(name, surname);
this.childs = childs;
}
public Parent() {
super();
childs = new ArrayList<Child>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public void addChild( Child child )
{
if( !childs.contains(child) )
{
child.setParent(this);
childs.add(child);
}
}
public List<Child> getChilds() {
return childs;
}
public void setChilds(List<Child> childs) {
this.childs = childs;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((childs == null) ? 0 : childs.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((surname == null) ? 0 : surname.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Parent other = (Parent) obj;
if (childs == null) {
if (other.childs != null)
return false;
} else if (!childs.equals(other.childs))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (surname == null) {
if (other.surname != null)
return false;
} else if (!surname.equals(other.surname))
return false;
return true;
}
}
My test method:
#Test
public void testJson()
{
try
{
Parent p = new Parent(UUID.randomUUID().toString(), UUID.randomUUID().toString());
for (int i = 0; i < 10; i++) {
p.addChild(new Child(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
}
ObjectMapper om = new ObjectMapper();
String childJson = om.writeValueAsString(p.getChilds().get(0));
System.out.println(childJson);
} catch (Exception e)
{
e.printStackTrace();
}
}
The final output was:
{"name":"b86eab86-9858-4536-9c5c-d44d22810fc1","surname":"9a6249f0-58df-44e5-a1b9-31fbad6e9f49","parent":{"name":"74b0cd97-64a1-4547-ab22-4e4eedd0759b","surname":"a33c79f3-6f26-478b-9e24-7df96b3b1f68"}}
Sadly annotation are powerfull but not always they allow to you to obtain what you need and so you have to do it "by yourself"
I hope this can be usefull

Spring Data Rest - Exposing ID

I am trying to expose the Id of my domain on the Json response using Spring Data Rest, besides getting it on the self object. I try what I saw on the internet but it is not working. I am using Spring Boot and this is my starting class and my config class for exposing the Id.
package com.desingfreed;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("com.designfreed")
public class GaliasBackendApplication {
public static void main(String[] args) {
SpringApplication.run(GaliasBackendApplication.class, args);
}
}
package com.desingfreed.config;
import com.desingfreed.domain.Articulo;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
import org.springframework.stereotype.Component;
#Component
public class ConfigurationRest extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(Articulo.class);
}
}
package com.desingfreed.repositories;
import com.desingfreed.domain.Articulo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "articulos", path = "articulos")
public interface ArticuloRepository extends CrudRepository<Articulo, Long> {
}
package com.desingfreed.domain;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "STA11")
public class Articulo {
#Id
#GeneratedValue
#Column(name = "ID_STA11")
private Long id;
#Column(name = "COD_ARTICU")
private String codigo;
#Column(name = "DESCRIPCIO")
private String descripcion;
// #OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "articulo")
// private List<Precio> precios = new ArrayList<>();
public Articulo() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCodigo() {
return codigo;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
// public List<Precio> getPrecios() {
// return precios;
// }
//
// public void setPrecios(List<Precio> precios) {
// this.precios = precios;
// }
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Articulo articulo = (Articulo) o;
if (id != null ? !id.equals(articulo.id) : articulo.id != null) return false;
if (codigo != null ? !codigo.equals(articulo.codigo) : articulo.codigo != null) return false;
return descripcion != null ? descripcion.equals(articulo.descripcion) : articulo.descripcion == null;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (codigo != null ? codigo.hashCode() : 0);
result = 31 * result + (descripcion != null ? descripcion.hashCode() : 0);
return result;
}
#Override
public String toString() {
return "Articulo{" +
"id=" + id +
", codigo='" + codigo + '\'' +
", descripcion='" + descripcion + '\'' +
'}';
}
}
Although doing this I still can get the Id on the Json response, I still get like this:
"_embedded" : {
"articulos" : [ {
"codigo" : "111012082",
"descripcion" : "VIRGEN LEV. FRESCA X 500G",
"_links" : {
"self" : {
"href" : "http://localhost:8080/articulos/1"
},
"articulo" : {
"href" : "http://localhost:8080/articulos/1"
}
}
Thanks very much!
For your information, i've created a simple component to dynamically expose every id.
#Component
public class EntityExposingIdConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
try {
Field exposeIdsFor = RepositoryRestConfiguration.class.getDeclaredField("exposeIdsFor");
exposeIdsFor.setAccessible(true);
ReflectionUtils.setField(exposeIdsFor, config, new ListAlwaysContains());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
class ListAlwaysContains extends ArrayList {
#Override
public boolean contains(Object o) {
return true;
}
}
}

Store enums in database using hibernate

I need to store an object using Hibernate, but this object use an enum. I can store, but when I tried to retrieve it again, this fails with this error: "Studies is not mapped [FROM Studies]".
I tried with a lot of solutions in internet but nothing works. I use MySQL database
This is the enum:
public enum StudyStatus {
Created("Created"), Started("Started"), Closed("Closed");
private final String value;
StudyStatus(String value){
this.value = value;
}
public static StudyStatus fromValue(int value){
for (StudyStatus status : values()) {
if (status.value.equals(value)) {
return status;
}
}
throw new IllegalArgumentException("Invalid status: " + value);
}
public String toValue(){
return value;
}
}
This is the EnumUserType class
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.AbstractStandardBasicType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
import org.hibernate.usertype.EnhancedUserType;
import org.hibernate.usertype.ParameterizedType;
public abstract class AbstractEnumUserType<E extends Enum<E>, V> implements
EnhancedUserType, ParameterizedType {
public static int DEAFAULT_SQL_TYPE = Types.INTEGER;
private PreparedStatementSetter psSetter;
private AbstractStandardBasicType<?> basicType;
protected abstract Class<E> getEnumClass();
protected abstract Class<V> getValueClass();
protected abstract E convertEnum(V rawValue);
protected abstract V convertSqlValue(E enumValue);
protected int getSqlType() {
int sqlType = Types.OTHER;
switch (getValueClass().getName()) {
case "java.lang.String":
sqlType = Types.VARCHAR;
break;
case "java.lang.Integer":
sqlType = Types.INTEGER;
break;
default:
break;
}
return sqlType;
}
// ////////////////////////////
#Override
public int[] sqlTypes() {
return new int[] { getSqlType() };
}
#Override
public Class<?> returnedClass() {
return getEnumClass();
}
#Override
public boolean equals(Object x, Object y) throws HibernateException {
return (x == y);
}
#Override
public int hashCode(Object x) throws HibernateException {
return (x == null) ? 0 : x.hashCode();
}
#Override
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Object rawValue = basicType.nullSafeGet(rs, names[0], session, owner);
Object enumValue = (rawValue == null) ? null
: convertEnum((V) rawValue);
return enumValue;
}
#Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
psSetter.set(st, convertSqlValue((E) value), index);
}
}
#Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
#Override
public boolean isMutable() {
return false;
}
#Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
#Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
#Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
#Override
public void setParameterValues(Properties parameters) {
// Initialize Method
initBasicType();
initPreparedStatementSetter();
}
#Override
public String objectToSQLString(Object value) {
return '\'' + ((Enum<?>) value).name() + '\'';
}
#Override
public String toXMLString(Object value) {
return ((Enum<?>) value).name();
}
#Override
public Object fromXMLString(String xmlValue) {
// TODO
throw new IllegalAccessError();
// return Enum.valueOf(, xmlValue);
}
protected void initBasicType() {
switch (getSqlType()) {
case Types.VARCHAR:
basicType = StringType.INSTANCE;
break;
case Types.INTEGER:
basicType = IntegerType.INSTANCE;
break;
default:
break;
}
}
protected void initPreparedStatementSetter() {
// TODO
switch (getSqlType()) {
case Types.VARCHAR:
psSetter = new StringPreparedStatementSetter();
break;
case Types.INTEGER:
psSetter = new IntPreparedStatementSetter();
default:
break;
}
}
private static interface PreparedStatementSetter {
void set(PreparedStatement st, Object value, int index)
throws SQLException;
}
private static class StringPreparedStatementSetter implements
PreparedStatementSetter {
#Override
public void set(PreparedStatement st, Object value, int index) {
try {
st.setString(index, (String) value);
} catch (SQLException e) {
}
}
}
private static class IntPreparedStatementSetter implements
PreparedStatementSetter {
#Override
public void set(PreparedStatement st, Object value, int index) {
try {
st.setInt(index, (Integer) value);
} catch (SQLException e) {
}
}
}
}
The class with the enum
import java.util.ArrayList;
import ateam.capi.common.enums.StudyStatus;
public class Study {
private String id;
private String name;
private StudyStatus status;
private ArrayList<User> pollsters;
private Questionnaire actualQuestionnaire;
public Questionnaire getActualQuestionnaire() {
return actualQuestionnaire;
}
public void setActualQuestionnaire(Questionnaire actualQuestionnaire) {
this.actualQuestionnaire = actualQuestionnaire;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public StudyStatus getStatus() {
return status;
}
public void setStatus(StudyStatus status) {
this.status = status;
}
public ArrayList<User> getPollsters() {
return pollsters;
}
public void setPollsters(ArrayList<User> pollsters) {
this.pollsters = pollsters;
}
}
This is the XML to map the Study class
<hibernate-mapping package="ateam.capi.common.beans">
<class name="Study" table="Studies">
<id name="id" column="id"></id>
<property name="name"/>
<property name="status">
<type name="ateam.capi.capipersistence.utils.EnumUserType">
<param name="enumClassName">
ateam.capi.common.enums.StudyStatus
</param>
</type>
</property>
</class>
</hibernate-mapping>
Study DAO class
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import ateam.capi.capipersistence.utils.HibernateUtil;
import ateam.capi.common.beans.Questionnaire;
import ateam.capi.common.beans.Study;
public class DAO_Study {
private Session session;
private Transaction tx;
public void saveStudy(Study study) throws HibernateException{
try{
initOperations();
session.save(study);
tx.commit();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
}
public void deleteStudy(Study study) throws HibernateException{
try{
initOperations();
this.session.delete(study);
this.tx.commit();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
}
public List<Study> getStudiesList() throws HibernateException{
List<Study> studiesList = null;
try{
initOperations();
String hql = "FROM Studies";
Query query = session.createQuery(hql);
studiesList = query.list();
} catch (HibernateException ex){
handleException(ex);
throw ex;
} finally{
if (session!=null){
session.close();
}
}
return studiesList;
}
private void initOperations() throws HibernateException{
HibernateUtil.createSession();
this.session = HibernateUtil.getSessionFactory().openSession();
this.tx = this.session.beginTransaction();
}
private void handleException(HibernateException ex) throws HibernateException{
this.tx.rollback();
System.out.println(ex.getStackTrace());
throw ex;
}
}
I use Java7 with hibernate 4.1.8, I found other solutions but dont work in java7
Any Idea?
Thanks!
Shouldn't your query look like from study instead of from studies? Studies is the table not the defined entity.