JPA (EBeans) Errors with Relations - html

First of all I am programming a webapplication with Playframework 2.2.2 which is using Ebeans.
I will start with the code because then it is easier to explain what my problem is:
This is one of my models:
#Entity
public class Topic extends Model {
#Id
private String title;
private String description;
#ManyToOne
private User createdBy;
private Integer popular;
#Formats.DateTime(pattern="dd/MM/yyyy")
private Date created;
private boolean over18;
#ManyToMany(cascade = CascadeType.REMOVE)
private List<Tag> tags;
}
The model has this method:
/**
* Return the number of opinions that exist on a specific Topic
*/
public int countOpinions() {
return Opinion.find.where().eq("topic", this).findRowCount();
}
This is my second relevant model:
#Entity
public class Opinion extends Model {
#Id
private Long opinionId;
#Constraints.Pattern("pos|neg|neut")
private String type;
#ManyToOne
private Topic topic;
#ManyToOne
private User user;
private int rating;
private String text;
private boolean reported;
#ManyToOne
private Opinion parent;
}
containing this static method
public static Model.Finder<Long, Opinion> find = new Model.Finder<Long, Opinion>(Long.class, Opinion.class);
Here we have the call in the HTML
#topics.map { topic =>
<th scope="col" id="name">#topic.getTitle()</th>
<th scope="col" id="description">#topic.getDescription()</th>
<th scope="col" id="opinions">#topic.countOpinions()</th>
}
Problem:
Ok so the countOpinions() is not working correctly. I created some testvalues, which should show the value 2 for a specific test Topic, but it shows the value 0. Im not sure how Ebeans is saving those fields with a type that I have created for myself, but afaik it should work like this.
I have tried already to override the equals methods in the Models, cause I figured it may be used, but apparently it isnt.
Thx for every help.

I tested it quickly, works fine
private FakeApplication fakeApplication;
#Before
public void setup() {
fakeApplication = fakeApplication(inMemoryDatabase());
start(fakeApplication);
}
#After
public void tearDown() {
stop(fakeApplication);
}
#Test
public void countOpinionsTest() {
// given
Topic topic = new Topic();
topic.setTitle("test");
topic.save();
Opinion opinion1 = new Opinion();
opinion1.setOpinionId((long) 1);
opinion1.save();
Opinion opinion2 = new Opinion();
opinion2.setOpinionId((long) 2);
opinion2.save();
// when
opinion1.setTopic(topic);
opinion1.update();
opinion2.setTopic(topic);
opinion2.update();
// then
assertThat(topic.countOpinions()).isEqualTo(2);
}
Do you have your ebean config set and the entity in the according package (here models)?
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
ebean.default="models.*"

Related

findAll returns empty list

This is Repository interface
#Repository
public interface MenuStructureTblService extends JpaRepository<MenuStructureTbl, Integer> {
}
MenuStructureTbl Table
#Data
#Entity(name = "menu_structure_tbl")
public class MenuStructureTbl {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Integer menuId;
public String menuTitle;
public String menuText;
public Integer menuMotherId;
public String createDate;
public String updateDate;
}
I am banging my head on the wall, Returned list is empty.
This one returns null
#Repository
public interface MenuStructureTblService extends JpaRepository<MenuStructureTbl, Integer> {
#Query(value="SELECT * FROM menu_structure_tbl", nativeQuery = true)
Object justGetIT();
}
Returns null; I have checked the query, generates result. But, I do not know what is going on.
Let me know if you have any question.
My mistake, Conflict of Environment, i was checking against wrong environment.

SpringData JPA - Provided id of the wrong type for class . Expected: class java.lang.Integer, got class java.lang.Long

i'm facing this issue while using Spring JPA and trying to retrieve a List of objects.
This is the class i'm trying to retrieve
#Entity
#Table(name="OBJECTSTERMIC")
public class TermicObject {
#Id
#Column(name="TERMICID")
private long termicId;
#MapsId
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="OBJECTID",columnDefinition="INTEGER")
private Object object;
#Column(name="CONTECA_RIF")
private int contecaRif;
#Column(name="CONTECA_VAL")
private int contecaVal;
#Column(name="TYPE")
private String type;
//getters and setters
The Object class has the primary key on MySQL stored as an Integer, indeed this is Object
#Entity
public class Object {
#Column(name="OBJECTID")
#Id
#JsonProperty("OBJECTID")
private int objectId;
....
So, nowhere is set a Long...
Now, i simply call in a service class
#Override
public List<TermicObject> findAll() {
return repository.findAll();
}
and got this exception
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TypeMismatchException: Provided id of the wrong type for class it.besmart.db_eipo.persistence.model.Object. Expected: class java.lang.Integer, got class java.lang.Long; nested exception is java.lang.IllegalArgumentException: org.hibernate.TypeMismatchException: Provided id of the wrong type for class it.besmart.db_eipo.persistence.model.Object. Expected: class java.lang.Integer, got class java.lang.Long
Where is set that Object Id should be Long?
Have a look at definition of your repository. Does it have right generic type? do you have Integer as second parameter? IMHO this can be root cause. See proposed correct version:
#RepositoryRestResource
public interface TermicObjectRepository extends JpaRepository<TermicObject, Integer> {
public Optional<TermicObject> findById(Integer id);
public List<TermicObject> findAll()
}
As per #Lubo's answer, in my case I was having compatibility issues between String and Long types and as my model required a Long autogenerated id I had to change the repository from
public interface ProductRepository extends JpaRepository<Product, String> {
}
to
public interface ProductRepository extends JpaRepository<Product, Long> {
}
And my controller from
#RequestMapping(path = "/products/delete/{id}", method = RequestMethod.DELETE)
public void deleteProduct(#PathVariable(name = "id") String id) {
productRepository.deleteById(id);
}
to
#RequestMapping(path = "/products/delete/{id}", method = RequestMethod.DELETE)
public void deleteProduct(#PathVariable(name = "id") Long id) {
productRepository.deleteById(id);
}
You have to define your id as a Long datatype.
#Id
#Column(name="TERMICID")
private Long termicId;
also make a change in your repository interface:
public interface ProductRepository extends JpaRepository<Product, Long> {
}
Got this because
public class MyEntity {
#Id()
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private int id; // <-------- int
...
public long getId() { return id; } // <-------- long
}
Not completely sure, but I think this mapping
#Id
#Column(name="TERMICID")
private long termicId;
#MapsId
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="OBJECTID",columnDefinition="INTEGER")
private Object object;
Makes the id of the Object match the value of termicId which is a long.
use
Long.valueOf(intValue)
to cast int to Long type because you define type Long to #Id

JPA generate fails with JSON

I cound't find any solution to manage that fail, so I decided to create a new question. I have a simple class
#Entity
public class Reservation {
// private Integer RESERVATION_ID;
// private Integer id;
private long code;
private Date date;
private Client reservationClient;
private WashType reservationWashType;
private Vehicle reservationVehicle;
private Wash reservationWash;
private Worker reservationWorkerPesel;
private Review reservationReview;
private ReservationReminder reservationReminder;
}
Where I run a query like that:
#Query("SELECT r FROM Reservation r JOIN FETCH r.reservationReminder where r.reservationWorkerPesel = :worker")
List<Reservation> findByReservationWorkerPesel(#Param("worker") Worker worker);
And at first I everything looks nice, but then I do some operations like that:
public List<ReservationReminder> findByReservationWorkerPesel(Worker worker) {
List<ReservationReminder> reservationReminderList = new ArrayList<>();
List<Reservation> byReservationWorkerPesel = reservationDao.findByReservationWorkerPesel(worker);
for (Reservation r : byReservationWorkerPesel) {
if (r.getReservationReminder() != null && r.getReservationReminder().getChecked() == false)
reservationReminderList.add(r.getReservationReminder());
}
return reservationReminderList;
}
And after that when I see how JSON looks like - it's strange, because:
[{"reservationReminderId":2,"reservation":{"code":263022,"date":1487851200000,"reservationClient":{"clientPesel":"91122619197","name":"Client 1","surname":"Client 1","email":"client#wp.pl","phone":"234567890","accountNumber":"34567897654345678987654356","clientUser":{"userId":3,"login":"client","passwordHash":"$2a$10$0jJMMzeh2CTRagk3hwRSlurx.mxLgR1aAUQOYBD9QFqbISeoTSVN.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":
....
[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":"$2a$10$6WrmwpwOdhv6UXBo2mYq8ucKiQTwvIwTHw23myo6.oujflh8pqKR.","userRole":{"roleId":3,"name":"CLIENT","users":[{"userId":8,"login":"clien5","passwordHash":{"timestamp":1489015140465,"status":200,"error":"OK","exception":"org.springframework.http.converter.HttpMessageNotWritableException","message":"Could not write content: Infinite recursion (StackOverflowError) (through reference chain: com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]-
...
\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"]->com.carwash.domains.Role[\"users\"]->org.hibernate.collection.internal.PersistentBag[0]->com.carwash.domains.User[\"userRole\"])","path":"/api/reservationreminder"}
What am I doing wrong?
Perhaps it can say you something - I don't why after making a GET method (only get) I got some those bugs?
You have a Infinite recursion between your User and UserRole object. Whenever a user is serialized his related user roles are also serialized. Since user roles does also have a relation back to the user you have the recursion.
Solution to this could be to use #JsonManagedReference (added to the relation in User) and #JsonBackReference (realtion at UserRoles). See also here: Infinite Recursion with Jackson JSON and Hibernate JPA issue
#Entity
public class User
...
#JsonManagedReference
private Set<UserRole> userRoles;
#Entity
public class UserRole
...
#JsonBackReference
private User user;
#JsonManagedReference would mean that during serialization the relation part is taken into account. So the related user roles would be also serialized. Since there the related connection is marked with #JsonBackReference serialization stops to go further.
#KLHauser
So how to manage the case if I have a class
#Entity
public class ReservationReminder {
private int reservationReminderId;
private Reservation reservation;
private boolean isChecked;
private Date checkedDate;
and Reservation class
#Entity
public class Reservation {
// private Integer RESERVATION_ID;
// private Integer id;
private long code;
private Date date;
private Client reservationClient;
private WashType reservationWashType;
private Vehicle reservationVehicle;
private Wash reservationWash;
private Worker reservationWorkerPesel;
private Review reservationReview;
private ReservationReminder reservationReminder;
#Entity
public class Worker {
private String workerPesel;
private String name;
private String surname;
private Date startDateWorking;
private String accountNumber;
private List<Review> workerReview;
private Adress workerAdress;
private List<LaborHistory> workerLaborHistory;
private Wash workerWash;
//private List<WorkerWorkerTime> workerWorkTime;
// private Role WORKER_ROLE;
private User workerUser;
private List<Reservation> workerReservation;
And I'd like to load ReservationReminder class with Worker from Reservation class? If I use #JsonIgonre like that
#OneToOne(mappedBy = "reservationReminder", fetch = FetchType.LAZY)
#JsonIgnore
public Reservation getReservation() {
return reservation;
}
I only got a Json with checkedDate, isChecked and reservationReminderId from ReservationReminder

NodeEntity wont persist

I have the following NodeEntity:
#NodeEntity(label = "Book")
public class Book{
private Long id;
private String content;
#Relationship(direction = Relationship.OUTGOING, type="WRITTEN_BY")
private User author;
}
where User is
#NodeEntity(label = "User)
public class User{
private Long id;
private String username;
}
and the BookRepository
#Repository
public interface BookRepository extends GraphRepository<Book> {
}
I've build a simple Rest-Controller to store a Book in the DB.
#Controller
#ResponseBody
#RequestMapping(path = "/books", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional
public class BookController {
#Autowired
private BookRepository bookRepo;
#RequestMapping(method = RequestMethod.POST)
public Book createBook(#RequestBody Book book) {
return bookRepo.save(book);
}
When I now POST a Book the JSON
{
"content":"Test content",
"author":{
"username":"Test-Username"
}
}
to the controller, two things happen that confuse me:
First, the author in the book-object is null, although both the Book and the User have their default constructor.
Secoundly: The Book doesn't get persisted. There is no error, I just get the same book-object returned (with the author still null) but still with a null id.
Querying MATCH n RETURN n on the neo4j client also yields nothing.
I tried removing the User object from the `Book, thinking the fault was there, but I still get the same behavior.
What am I doing wrong?
Sometimes talking about a problem alone solves it... I've forgotten to put the package that contained the Book into the
#Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(/*Package of Book should have been here*/);
}
in the Application

How to store the same entity in mulitple lists in Hibernate using JPA

Im very new to Hibernate so this will probably a easy task for you guys.
As the Topic says I'm trying to reference the same entity in multiple Lists. But when I try to do so I get an exception saying: "Duplicate entry '5' for key 'military_id'".
I googled but could not find a solution to my problem.
I have an Entity called MilitaryUnitData like this:
#Entity
public class MilitaryUnitData implements IMovable{
private long Id;
//snip
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
//snip
}
and a class City where I want to store my units in.
#Entity
public class CityData {
private Collection<MilitaryUnitData> military = new ArrayList<MilitaryUnitData>();
private String name;
//snip
#Id
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany
#Column(nullable=false)
public Collection<MilitaryUnitData> getMilitary() {
return military;
}
public void setMilitary(Collection<MilitaryUnitData> military) {
this.military = military;
}
//snip
}
The problem occurs when I want to put a Unit into 2 cities at the same time.
How do I have to change the mapping to achive this?
Thx in advance.
I'm trying to reference the same entity in multiple Lists
After looking at your code, I think you mean, that the same MilitaryUnitData is used in several CityData?
IF this is correct, than the realtion ship is a M:N relation ship, and you need to use a #ManyToMany instead of an #OneToMany.