java.sql.SQLException: Field 'user_id' doesn't have a default value - java

This error occurs when my Postmapping method tries to save a quiz.
Here's the controller.
`
#PostMapping("/quizzes")
public Quiz postQuiz(#Valid #RequestBody Quiz quiz) {
return quizRepo.save(quiz);
}
Now here is the User entity whose association is the Quiz entity (it has 5 fields).
public class User {
//other fields/columns
#OneToMany(targetEntity = Quiz.class, cascade = CascadeType.ALL)
#JoinColumn(name = "user_id", referencedColumnName = "id")
private List<Quiz> quizzes;
}
Theuser_id` field is the foreign key in the quiz table and not a declared field in the Quiz class/entity.
I was thinking just declaring the relationship will populate the foreign key column, in this case user_id, will just be the primary key of the owning entity but it seems at the the time of saving in the PostMapping method, the user_id is null. I've tried anything I possibly can but to no avail.

Related

Hibernate #OneToOne Unidirectional Mapping...Cascade Delete

I'm working on a Spring Boot Application with Hibernate and I'm just trying to understand the correct way to approach a OneToOne mapping when it comes to using cascade delete.
So, we have a User table and a PasswordResetToken table. A user has standard user columns: id, username, password, email.
A password reset token has an id, a FK to userId, and a string for a token.
So, my question now is: how do I correctly model this so we can properly cascade delete?
My thought process is that we have a unidirectional mapping since password reset token has a FK to user, and user does NOT have a FK to password reset token.
So I would think that we would place the #OneToOne on our PasswordResetToken class in Java and not have a reference to PasswordResetToken in our User class, but then the PasswordResetToken class will have a reference to a User object.
But, through some stackoverflowing, I found that people would have the child object (PasswordResetToken) inside the parent object (User) despite the parent object's table not having a reference to the child object's table (since the User table doesn't have a PasswordResetToken in it) which allows for adding the cascade remove to the #OneToOne annotation which means that when a User gets deleted, all children will get deleted as well.
So, which way is the right way to model this relationship?
Thanks for your time
There are many ways to solve your problem. Some are less, some are more efficient.
Bidirectional with foreign key
#Entity
public class PasswordResetToken {
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User User;
// other fields
}
#Entity
public class User {
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL,
fetch = FetchType.LAZY, optional = false)
private PasswordResetToken passwordResetToken;
// other fields
}
Bidirectional with principal/parent's primary key as foreign key
Since it's 1-1 relationship, you could use User's ID as a primary key for PasswordResetToken table.
#Entity
public class PasswordResetToken {
#OneToOne(fetch = FetchType.LAZY)
#MapsId
private User User;
// other fields
}
#Entity
public class User {
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL,
fetch = FetchType.LAZY, optional = false)
private PasswordResetToken passwordResetToken;
// other fields
}
Unidirectional
If you want to have unidirectional mapping, and to have PasswordResetToken entity as part of User entity, you'll have to move the foreign key to User table, since #JoinColumn has to be applied on entity owning the foreign key.
#Entity
public class User {
#OneToOne(cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
#JoinColumn("password_reset_token_id") // FK in User table
private PasswordResetToken passwordResetToken;
// other fields
}
As for performance, the most efficient is bidirectional with #MapsId. Bidirectional with #JoinColumn is less efficient, and I'm not sure about unidirectional mapping. One to one mappings are not that common in practice, and I'm not sure how often people use unidirectional mapping. Probably not at all, since the foreign key is usually on dependent side.
I don't know how big the token is, but what is wrong with storing the token in the User entity as simple column? You can abstract some parts by using an #Embeddable but really this should IMO be in the same table. If you are concerned with the amount of data fetched, you should be using DTOs to reduce the amount of data.

Hibernate insert with join and foreign key

I have some problem with insert in hibernate.
Suppose I have 2 entity
#Entity
public class User{
#Id
#GeneratedValue
int user_id;
String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "utente_id")
list<City> cities;
}
#Entity
public class City{
int user_id
int city_id
}
if I try a create class User and add a list of city but when I try to save, receive this error:
Caused by: java.sql.SQLException: Foreign key constraint violation occurred
this because user_id in class City must be equal at user_id in User, but hibernate first inserts and then updates.
How do i revolve this?
Try first to persist the User object to DB.
Only after you persist you can get the generated value of user_id.
Then you can create the City object, set the user_id field, and persist it.

how to mapping an OneToMany relation with Weak Entity in Hibernate

I need to map a OneToMany relationship in hibernate, with the JPA annotations, in which is involved a weak entity.
For example
Table orders:
CREATE TABLE orders(
idorder serial NOT NULL,
note varchar(30),
CONSTRAINT orders_pkey PRIMARY KEY (idorder)
)
Table OrderItems:
CREATE TABLE orderitems(
idorder integer NOT NULL,
iditem serial NOT NULL,
qnt integer,
CONSTRAINT orderitems_pk PRIMARY KEY (idorder, iditem),
CONSTRAINT fk_orderitems FOREIGN KEY (idorder)
REFERENCES orders (idorder) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
Within my class "Orders" I have realized the method getOrderItem() in this way:
// i need cascadeType.All here
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "order")
public Set<OrderItem> getOrderItems() {
return items;
}
now,
not being able to know the identifier that will be assigned to a new order
prior to insertion, such as Annotations can I use within the class OrderItem in order to submit automatically (in cascade mode) the correct idOrder?
my goal is to get a situation like this.
Order myOrder = new Order();
// myOrder.setId(1) not necessary
myOrder.setNote("orderNote");
OrderItem firstItem = new OrderItem();
// firstItem.setIdOrder() no need to specify idorder
// firstItem.setId(12);
firstItem.setName("firstItem");
firstItem.setQnt(2);
OrderItem secondItem = new OrderItem();
// secondItem.setId(13);
secondItem.setName("secondItem");
secondItem.setQnt(4);
Set<OrderItem> items = new HashSet<OrderItem>();
items.add(firstItem);
items.add(secondItem);
myOrder.setItems(items);
OrderDAO dao = new OrderDAO();
dao.save(myOrder); // i want inser all items in cascade with the idOder assigned to "myOrder"
Ok I will try to add Entity classes you need to have above given scenario.
#Entity
#Table(name="orders")
public class Order{
#Id
#GeneratedValue
#Column(name="ID")
private Long id;
#Column(name="note ")
private String note ;
#OneToMany(mappedBy="orders")
private Set<OrderItem> orderitems;
// Getter and Setter methods
}
And then the OrderItem class
#Entity
#Table(name="OrderItems")
public class OrderItem{
#Id
#Column(name="iditem")
private Long iditem;
#Column(name="qnt")
private long qnt ;
#ManyToOne
#JoinColumn(name="idorder")
private Order order;
public OrderItem() {
}
// Getter and Setter methods
}
Also i dint get which column your setname maps to.. and iditem isnt generated value its assigned id type
Ok then it also could be issue about inverse that who could be the relationship owener .. Inverse=true is same behaviour as mappedBy attribute usage so try changing it..
Let me know if this works or you get a issue while trying this out..

JPA - Mapping OneToMany association between the same table using an intermediate table

I'm creating an application where one large aspect is the ability for users to share content with friends. I'm trying to represent this in the object model and I'm having trouble getting the association to work properly. I'm using a mapping table that records the friender and the friendee, both of which are represented by the primary key (id) of the user. A user can have many friends, and also be referenced by other users. This is what the schema looks like:
Users:
int user_id (PK)
varchar(32) email
varchar(64) password
Users_Map:
int users_map_id (PK)
int friendee_id (FK references users(user_id))
int friender_id (FK references users(user_id))
And this is how I have the User entity set up:
#Data
#Entity
#Table(name = "users")
public class User extends AbstractPersistable<Long> {
#Id
#Column(name = "user_id")
private Long id;
#Column
private String email;
#Column
private String password;
#OneToMany
#JoinTable(name = "users_map",
joinColumns = { #JoinColumn(name = "friender_id") },
inverseJoinColumns = { #JoinColumn(name = "friendee_id") })
private List<User> friends;
}
I run into the following error when deploying the application:
org.hibernate.AnnotationException: A Foreign key refering
com.x.webapp.data.entity.User from
com.x.webapp.data.entity.User has the wrong number of
column. should be 2
I've tried quite a few other configurations, including adding a "referencedColumnName" attribute to each #JoinColumn, but they have also yielded errors. I'm also not entirely sure whether the schema I currently have is the best way to go about mapping users together.
I appreciate any help!
Removing the extension of AbstractPersistable fixed the problem - that contained an #Id reference and clashed with the #Id reference I put inside of User.

JPA #OneToMany join on part of a multipart key

A Profile table has a one to many association with a Privilege table. The privilege table has a multipart key, of a profile_id and a privilege_id. I want to join from the Profile table to the Privilege table only on the profile_id and get back a collection of privileges.
In my Profile class I have
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "PROF_ID")
public List<ProfilePrivilegeEO> getProfilePrivileges()
{
return m_profilePrivileges;
}
My Privilege class has
private ProfilePrivilegeId m_profileId;
#EmbeddedId
public ProfilePrivilegeId getProfileId()
{
return m_profileId;
}
Where ProfilePrivilegeId is
#Embeddable
public class ProfilePrivilegeId
implements Serializable
{
private Integer m_profileId;
private Integer m_privNumber;
#Column(name = "PROF_ID")
public Integer getProfileId()
{
return m_profileId;
}
#Column(name = "PRIV_NUM")
public Integer getPrivNumber()
{
return m_privNumber;
}
.....
}
However, when i do that the static weaver says:
The #JoinColumns on the annotated element [method getProfilePrivileges] from the entity
class [class com.acme.ProfileEO] is incomplete. When the source entity class uses a
composite primary key, a #JoinColumn must be specified for each join column using the
#JoinColumns. Both the name and the referencedColumnName elements must be specified in
each such #JoinColumn.
However, the Profile table has no knowledge of privilege_ids... I don't see why JPA should demand that i specify both keys of the privilege table, that's just an arbitrary decision made by jpa with no valid reason why... What do i need to do to get this to work? (I am using EclipseLInk.)
Create an PrivilegeId class that encapsulate the ids. Make that class #Embedded and put it in the Privilege with #EmbeddedId.
In the PrivilegeId class, put an #OneToMany to the Profile and the privilege id.

Categories

Resources