OneToOne and OneToMany not storing Parent Id (IdClass) - java

I am currently working on a project with following data structure:
public class PinaColadaId implements Serializable {
private UUID id;
#Temporal(TemporalType.TIMESTAMP)
private Date time;
// Constructor + Getters and Setters
}
#Entity
#Table(name = "pina_coladas")
#IdClass(PinaColadaId.class)
public class PinaColadaEntity {
#Column(columnDefinition = "char(255)")
#Type(type="org.hibernate.type.UUIDCharType")
private #Id UUID id;
private #Id #Temporal(TemporalType.TIMESTAMP) Date time;
#OneToOne(mappedBy = "entityID", cascade=CascadeType.ALL)
private PineappleWrapper pineapple;
#OneToMany(mappedBy = "entityID", cascade=CascadeType.ALL)
private List<CoconutWrapper> coconuts;
// Constructor + Getters and Setters
}
#Entity
public class PineappleWrapper {
private #Id #GeneratedValue long id;
private String manufacturer;
private String origin;
#OneToOne
private PinaColadaEntity entityID;
// Constructor + Getters and Setters
}
#Entity
public class CoconutWrapper {
private #Id #GeneratedValue long id;
private int shipmentNumber;
private int juice;
#ManyToOne
private PinaColadaEntity entityID;
// Constructor + Getters and Setters
}
The issue is that Spring Boot together with Hibernate and JPA correctly generate all the tables in my database, however when I attempt to store PineappleWrapper or CoconutWrapper, it stores all the values of PineappleWrapper and/or CoconutWrapper except for the id and time of the parent. The columns are generated yet they store the value "null".
Any and all help is much appreciated, -AwesomeDude091
Edit: I am aware of the JoinColumn annotation and it proposed implementation in my Wrapper classes, but I do not know how to use them with my two ID variables (id and time)

Related

Can't save entity with composite key

I get an exception when I try to save entities when composite key is used. Here is the exception, models and repository I try to save to. Can anyone help?
org.springframework.beans.TypeMismatchException: Failed to convert
property value of type 'org.CheckType_$$_jvst96c_4' to required type
'int' for property 'checkType'; nested exception is
java.lang.IllegalArgumentException: Cannot convert value of type
'org.CheckType_$$_jvst96c_4' to required type 'int' for property
'checkType': PropertyEditor
[org.springframework.beans.propertyeditors.CustomNumberEditor]
returned inappropriate value of type 'org.CheckType_$$_jvst96c_4'
#Entity
public class CheckType {
#Id
private int id;
#NotNull
private String name;
#OneToMany(mappedBy = "checkType")
private List<ClientCheck> checks;
//getters and setters
}
#Entity
public class Offer {
#Id
#Column(name = "offerid")
private Integer offerId;
//...
#OneToMany(mappedBy = "offer")
private List<ClientCheck> clientCheckList;
//getters and setters
}
#Entity
#IdClass(ClientCheckId.class)
public class ClientCheck {
#Id
#ManyToOne
#JoinColumn(name = "offer_id", referencedColumnName = "offerid")
private Offer offer;
#Id
#ManyToOne
#JoinColumn(name = "check_type_id", referencedColumnName = "id")
private CheckType checkType;
#Id
private Date timestamp;
private String result;
//getters and setters
}
public class ClientCheckId implements Serializable {
private int offer;
private int checkType;
private Date timestamp;
//getters and setters
//equals and hashCode
}
public interface ClientCheckRepo extends JpaRepository<ClientCheck, ClientCheckId> {
}
If another entity is a part of composite key, you must declare that entity in your ID class, not its ID:
public class ClientCheckId implements Serializable {
private int offer;
private CheckType checkType;
private Date timestamp;
//getters and setters
//equals and hashCode
}
The error message is quite readable if you want how Hibernate works: org.CheckType_$$_jvst96c_4 is the enriched version of your class, which Hibernate tries to assign to checkType field of ClientCheckId via reflection, and fails because of type incompatibility.

Getting Errors with #ManyToOne in Play using #MappedSuperclass

I am trying to set up our database in our project. But I get some errors, when I try to use #ManyToOne and#OneToMany on a #MappedSuperclass Entity:
#MappedSuperclass
public abstract class Person extends Model{
//public abstract class Person {
// ATTRIBUTES
#Column(columnDefinition = "varchar(20) not null")
private String firstName;
#Column(columnDefinition = "varchar(20) not null")
private String lastName;
#Column(columnDefinition = "varchar(20) not null")
private String password;
#Column(columnDefinition = "varchar(50) not null")
private String eMail;
#Column(columnDefinition = "varchar(8) not null")
private String svn;
private static int staticId = 0; // Identifier, staticId is unique.
#Id
#Column(columnDefinition = "integer not null")
private int id;
#Column(columnDefinition = "integer")
private int age;
#Column(columnDefinition = "varchar(10)")
private String telephoneNumber;
#Column(columnDefinition = "decimal(10,2)")
private double salary;
#Column(columnDefinition = "boolean")
private boolean allowedOvertime;
//#OneToMany(mappedBy = "person")
private List<TimeEntryMonth> listTimeEntryMonth;
#OneToMany(mappedBy = "person")
private List<Vacation> listVacation;
#OneToMany(mappedBy = "person")
private List<SickLeave> listSickLeave;
One of the classes who extends from Person:
#Entity
public class Employee extends Person {
// ATTRIBUTES
private String position;
private Boss boss;
And one of the #OneToMany relations:
public class SickLeave extends Model {
/* ATTRIBUTES */
#Id
private int id;
#ManyToOne
private Person person;
private int personIdSL;
private String reason;
If I compile my whole Project without the #ManyToOne and #OneToMany, it will work fine. But with the it will lead into som errors:
Error injecting constructor, java.lang.RuntimeException: Error reading
annotations for models.SickLeave
I tried to delete the abstract and replaced #MappedSuperclass with #Entity and the project works. So I think that I cant have #OneToMany and #ManyToOne relations on a #MappedSuperclass, But I dont want to refactor my whole project
Is there any (easier) way to handle such issues?
Thank you.
Person is not an Entity, so you can't use OneToMany to it. You will need to make Person an Entity or point to Employee, which seems to make more sense to me.

How to adjust relations between entities using Hibernate mapping?

I have such a simple scheme
and the following entities:
#Entity
public class Ticket {
#Id
#GeneratedValue
private Integer id;
#ManyToOne
private Event event;
#OneToOne
private User user;
#Embedded
private Seat seat;
private TicketState state;
private Float price;
// getters, setters, etc.
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
#OneToOne
private Movie movie;
#Embedded
private Auditorium auditorium;
private LocalDateTime startDateTime;
#OneToMany
private Set<Ticket> tickets = new HashSet<>();
// getters, setters, etc.
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
#Enumerated(EnumType.STRING)
private UserRole role;
private String name;
private String email;
private Instant birthday;
#OneToMany
private List<Ticket> tickets = new ArrayList<>();
private boolean lucky;
// getters, setters, etc.
#Embeddable
public class Auditorium {
private Integer id;
private String name;
private Integer seatsNumber;
#ElementCollection
private List<Integer> vipSeats;
// getters, setters, etc.
Also these entities was added to hibernate.cfg.xml.
Than I run app I have the following exception:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.epam.spring.core.domain.Event column: id (should be mapped with insert="false" update="false")
At first glance I don't see any duplications in Event, as mentioned in exception. What should I fix in entities mapping description to resolve the problem according my scheme? Thank you!
Both Event and Auditorium map to column named id.
Specify a different column name in Auditorium or use #AttributeOverride in Event to override the default name.
When you map an entity with annotations, you do not need to repeat yourself on hibernate.cfg.xml. Try to delete it e run your code again.
Updating my answer based on Dragan Bozanovic's, Auditorium should NOT have an #Id annotated field (but we can't see that from your code, if it has).

#OneToOne Hibernate with annotations. Can't properly save

I can't make my foreign keys auto generate using hibernate and jpa with annotations. Everything seems ok, The entries are saved in database. All the date come from one form which, when submited creates an User object with ModelAttribute and then saves it in Database.
Here are my beans. Anything else i should add ?
#Entity
#Table(name="adress")
public class Adress implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="adress_id")
private Integer adressId;
#NotBlank(message="The city must be completed")
#Column(name="city")
#Size(min=5,max=30)
private String city;
#NotBlank(message="The street must be completed")
#Column(name="street")
#Size(min=5,max=30)
private String street;
#NotNull(message="The street number must be completed")
#NumberFormat
#Column(name="street_no")
private Integer streetNo;
#OneToOne
#JoinColumn(name="user_id")
private User user;}
and the other one:
#Entity
#Table(name="users")
public class User implements Serializable {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;
#NotBlank(message="Username can't be blank")
#Size(min=5,max=30)
#Column(name="username")
private String username;
#NotBlank(message="Password field can't be blank")
#Size(min=5,max=30)
#Column(name="password")
private String password;
#NumberFormat
#NotNull(message="Age field must not be blank")
#Column(name="age")
private Integer age;
#Column(name="message")
#Size(min=0,max=100)
private String message;
#Column(name="date")
#DateTimeFormat(pattern="dd/mm/yyyy")
private Date dateCreated;
#OneToOne(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Adress adress;
+getters and setters for them
public void save(T entity){
sessionFactory.getCurrentSession().save(entity);
}
If I understand you correctly and you're trying to get Hibernate to set the foreign key on your related record this might help. Try getting rid of mappedBy and instead specify the JoinColumn. This works for me on a one to many:
The order:
#Entity
#Table(name = "`order`")
public class Order implements Serializable {
#Id
#GeneratedValue
private Long id;
// Order columns...
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private Set<Item> items;
}
The item:
#Entity
#Table(name = "item")
public class Item implements Serializable {
#Id
#GeneratedValue
private Long id;
// Item columns...
#ManyToOne(optional = false)
#JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
private Order order;
}
in adress class
#OneToOne(mappedBy="adress")
private User user;
and in user class
#OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER,optional=false)
#PrimaryKeyJoinColumn
private Adress adress;

Hibernate One-to-Many mapping by date range?

I want to change Train.trainFares from transient to mapped to the TrainFare class. However, I want to limit the TrainFares to those that are active for the Train.ddate. How do I do this?
I have found a Hibernate Jira issue which I believe might be the source of my problems. Has anyone else come across this issue? Did you find a workaround?
#Entity
#Table(name = "TRAIN")
public class Train {
#EmbeddedId
private TrainPK id;
#Column
private String trainType;
#Transient
private List<TrainFare> trainFares;
#Embeddable
public static class TrainPK {
#Column
private String company;
#Column
private Date departDate;
#Column
private String trainNumber;
}
... setters & getters
}
#Entity
#Table(name = "SEATRATE")
public class SeatRate {
#EmbeddedId
private SeatRatePK id;
#Column
private Date expiryDate;
#Column
private String trainNumber;
#Embeddable
public static class SeatRatePK {
#Column
private String company
#Column
private Date effectiveDate;
}
... setters & getters
}

Categories