Ebean: #OneToMany to the same Entity - java

I have the following scenario where a User can make a Reservation on a Campaign.
Eg. User wants to reserve a Campaign(eg 20% off on a book). I want the reservation table to look like this: |id|user_id|campaign_id|
User can make many reservations.
Campaign can be reserved by many users.
Reservation will contain what user reserved what campaign.
User.java
#Entity
public class User extends Model {
#Id
public Long id;
public String username;
public String password;
#OneToMany(cascade = CascadeType.PERSIST)
public List<Reservation> reservations;
}
Campaign.java
#Entity
public class Campaign extends Model {
#Id
public Long id;
public String name;
#OneToMany(cascade = CascadeType.PERSIST)
public List<Reservation> reservations;
}
Reservations.java
#Entity
public class Reservation extends Model {
#Id
public Long id;
}
How come this doesn't work?
EDIT:
I get a reservation table that has an id and an user_id, but no campaign_id

You may consider doing it like this,
User.java
#Entity
public class User extends Model {
#Id
public Long id;
public String username;
public String password;
#OneToMany(cascade = CascadeType.PERSIST,mappedBy="user")
public List<Reservation> reservations;
}
Campaign.java
#Entity
public class Campaign extends Model {
#Id
public Long id;
public String name;
#OneToMany(cascade = CascadeType.PERSIST,mappedBy="campaign")
public List<Reservation> reservations;
}
Reservation.java
#Entity
public class Reservation extends Model {
#Id
public Long id;
#ManyToOne
public User user;
#ManyToOne
public Campaign campaign;
}

Related

OneToMany relation: updating the Many side makes it disapper from the One side?

So I got these two classes in a Spring Boot/Hibernate project, Doctor:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
public class Doctor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotBlank
private String name;
#OneToMany(mappedBy = "doctor")
#JsonManagedReference
private List<Patient> patients;
}
And the Patient:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
public class Patient {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotBlank
private String name;
#Range(min=1, max=150)
private int age;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "doctor_id")
#JsonBackReference
private Doctor doctor;
#OneToOne
private Receipt receipt;
}
They got the following columns generated :
Doctor : id, name
Patient: id, age,name, doctor_id,receipt_id (dont worry about the receipt part)
The problem is that by updating a Patient (with a regular JPARepository save() method) I can get a updated Patient with findall/findbyId but it disappears from the Doctor's list.
I figure my associations annotations are the problem, any idea how would it work?
!Edit!
here is the Controller for Patient:
#RestController
#RequestMapping("/patient")
public class PatientController {
private PatientService patientService;
public PatientController(PatientService patientService) {
this.patientService = patientService;
}
#GetMapping
public List<Patient> getAllPatients() {
return patientService.getAllPatients();
}
#GetMapping ("/{id}")
public Patient getPatientById(#PathVariable Long id){
return patientService.getPatientById(id);
}
#DeleteMapping("/{id}")
public void deletePatientById(#PathVariable Long id) {
patientService.deletePatientById(id);
}
#PostMapping
public void savePatient(#RequestBody Patient patient) {
patientService.save(patient);
}
#PutMapping("/{id}")
public void updatePatientById(#PathVariable Long id, #RequestBody Patient patient) {
patient.setId(id);
patientService.save(patient);
}
}
The save in the service layer is just the regular JPARepository save method.

Spring DATA - How to load a Collections of ids for an ManyToMany relation without load the whole LazyProxyObject [duplicate]

I have two Entities in my Spring-Boot Application:
User.java
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String firstname;
String lastname;
String username;
String password;
}
and
Role.java
Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
String description;
}
for my MySql database
I have excluded the getter and setter methods for this question.
I want to realise a Many-to-Many-Relationship between both Entities. Every user should be able to assign multiple roles to himself
I already Created a mapping table for both tables in my database. It has the rows
user_id
role_id.
I also created a new Entity UserRole.java which looks like this:
#Entity
#Table(name = "user_role")
public class UserRole implements Serializable{
private User user;
private Role role;
#Id
#ManyToOne
#JoinColumn(name = "user_id")
public User getuser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Id
#ManyToOne
#JoinColumn(name = "role_id")
public Role getrole(){
return role;
}
public void setRole(Role role){
this.role = role;
}
}
Now my question: is this construction correct? If yes, how do i add existing roles to an existing user and get the roles of this user in spring-boot?
You can find any tutorial connected with many-to-many relationship using Hibernate/Spring Data, example:
Spring Data many-to-many
With your model it's simple to add the relationship mappings, like this:
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable
private Set<User> users;
}
and this:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
private String username;
private String password;
#ManyToMany(mappedBy = "users")
private Set<Role> roles;
}

Hibernate one-to-many relationship java.sql.SQLIntegrityConstraintViolationException: Column 'person_id' cannot be null

I'm new to hibernate, learn doc save persistent object
followed hibernate doc this is person and phone relationship one-to-many
#Entity
#Table(name = "phone")
public class Phone {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "number")
private String number;
#ManyToOne(fetch = FetchType.LAZY)
private Person person;
//omit setter and getter
}
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private List<Phone> phones = new ArrayList<>();
//omit getter and setter
}
I'm persistent person and add one phone the error be throw
#Test
public void say() {
Person person = new Person();
person.setUsername("aaaa");
Phone phone = new Phone();
phone.setNumber("111");
person.getPhones().add(phone);
personService.save(person);
}
this is Dao persistent
public class PersonDaoImpl implements PersonDao {
#PersistenceContext
private EntityManager entityManager;
#Override
public void save(Person person) {
entityManager.persist(person);
}
Update service code, service just save person
#Service(value = "personService")
public class PersonServiceImpl implements PersonService {
#Autowired
private PersonDao personDao;
#Transactional
#Override
public void save(Person person) {
personDao.save(person);
}
}
error info:
23:35:47.059 [main] DEBUG org.hibernate.engine.spi.ActionQueue - Executing identity-insert immediately
23:35:47.062 [main] DEBUG org.hibernate.SQL -
insert
into
phone
(number, person_id)
values
(?, ?)
23:35:47.297 [main] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not execute statement [n/a]
java.sql.SQLIntegrityConstraintViolationException: Column 'person_id' cannot be null
Add the #GeneratedValue annotation to specify that the primary key for both entities will be populated outside of your code.
#Entity
#Table(name = "phone")
public class Phone {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Column(name = "number")
private String number;
#JoinColumn("person_id")
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Person person;
//omit setter and getter
}
public class Person {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String username;
#OneToMany(mappedBy = "person")
private List<Phone> phones = new ArrayList<>();
//omit getter and setter
}
Additionally, you need to persist the Person object instead of the Phone object because there is no cascade configured from Phone to Person. If you can't do that, switch the CascadeType on Person to none and put the cascade on the Phone as shown above.
You should also add a #JoinColumn annotation on the Phone entity so hibernate is aware of the foreign key column.
You Missed something. You can try with this.
Person Entity
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String username;
#OneToMany(mappedBy = "person")
private List<Phone> phones = new ArrayList<>();
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
//omit getter and setter
}
Phone Entity
#Entity
#Table(name = "phone")
public class Phone {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "number")
private String number;
#ManyToOne(cascade = CascadeType.PERSIST)
private Person person;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
//ommit setter and getter
}
Phone Dao
public interface PhoneDao {
public Phone save(Phone phone);
}
PhoneDaoImpl
#Repository
public class PhoneDaoImpl implements PhoneDao {
#PersistenceContext
private EntityManager entityManager;
#Override
public Phone save(Phone phone) {
return entityManager.merge(phone);
}
}
PersonDaoImpl
#Repository
public class PersonDaoImpl implements PersonDao{
#PersistenceContext
private EntityManager entityManager;
#Override
public Person save(Person person) {
return entityManager.merge(person);
}
}
Test Method
#Test
#Transactional
#Commit
public void say()
{
Phone phone = new Phone();
phone.setNumber("jghjkhk");
Person person = new Person();
person.setUsername("7576");
phone.setPerson(person);
Phone pers = phoneDao.save(phone);
Assert.assertNotNull(pers);
}
Try now. It will work.
I think that you need to set the value of the person->id and then also use an getter method to pass the id to your phone object instead of passing the person object
Normally people have hibernate set the id of an entity automatically with a surrogate key.
public class Person {
#Id #GeneratedValue // should pick an appropriate strategy here
private long id;
Since you don't have that you must either add it or set it yourself.
Person p = new Person();
p.setId(1); // hopefully unique
The same goes for phone.
As you are not having any generation type on your #Id and id is the primary key which can not be null so either you have to set value of id or have #GeneratedValue annotation on your id field and set strategy either as Auto or Identity.
You can also have your own sequence generation.
Also, you need to do same for the Phone class.

Spring JPA mapping - first steps

I have class User:
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
private String name;
private String password;
#ManyToMany
#JoinTable
private List<Role> roles;
}
Class Owner inherits from User
#Entity
public class Owner extends User {
private String pesel;
private String adress;
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
private List<Pet> pets;
}
and Owner had Pet
public class Pet {
#Id
#GeneratedValue
private Integer id;
private String name;
private String weight;
#ManyToOne
private Owner owner;
}
Why when starting the application gets the error:
org.springframework.data.mapping.PropertyReferenceException: No
property user found for type Pet!
--EDIT
First I have version, which was as follows:
now I try to share User instance to a doctor and the owner of the animal
The problem is that I do not know whether I am doing the mapping , and therefore wanted to ask whether it must look like
--edit2
I've simplified the scheme just a bit to better illustrate what happens
--edit3
Currently my Object's was presented:
#Entity
public class Pet {
#Id
#GeneratedValue
private Integer id;
private String name;
private String weight;
}
User
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
private String name;
private String password;
#ManyToMany
#JoinTable(name="user_roles")
private List<Role> roles;
}
PetOwner
#Entity
public class PetOwner extends User {
private String pesel;
private String adress;
#OneToMany(mappedBy="petOwner")
private List<Pet> pets;
}
I replace
#ManyToOne
private PetOwner petOwner;
for
#ManyToOne
private Owner petOwner;
and it works. Do you have a PetOwner class?
Also provide the log error to get more information about it

Mapping one of two classes that implements interface

Class has property that can be one of two class-types, that's why I try to create interface that class-types implement
#Entity
#Table(name = "users")
public class User{
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Long userID;
#Column(name="email")
private String email;
#OneToOne(mappedBy = "user")
private Login login;
... getters/setters
#MappedSuperclass
public interface Login {
User user = new User();
}
#Entity
#Table(name = "user_logins_social")
#IdClass(UserLoginSocialID.class)
public class UserLoginSocial implements Login{
#OneToOne
#JoinColumn(name="uid")
private User user;
...
#Entity
#Table(name = "user_logins_native")
public class UserLoginNative implements Login{
#OneToOne
#JoinColumn(name="uid")
private User user;
...
So I can't use target entity because both classes can be used. Here is error stack: org.hibernate.AnnotationException: Unknown mappedBy in: model.User.login, referenced property unknown: model.Login.user. Help me please
Cannot map or query on an inferface.
#MappedSuperclass should be able to use abstract class and class.
Please check: wikihttp://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Interfaces
#MappedSuperclass
public abstract class User{
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Long userID;
#Column(name="email")
private String email;
#OneToOne(mappedBy = "user")
private Login login;
// ... getters/setters
#Entity
#Table(name = "login")
public class Login{
#OneToOne
private User user;
}
#Entity
#Table(name = "user_logins_social")
#IdClass(UserLoginSocialID.class)
public class UserLoginSocial extends User{
//...
}
#Entity
#Table(name = "user_logins_native")
public class UserLoginNative extends User{
//...
}

Categories