Unable to insert into table in hibernate - spring-boot

I am trying to create new table and join with ManyToOne relation with my existing table
below is my implementation
New table
#Entity(name="request_city_id")
#Table(uniqueConstraints={#UniqueConstraints{columnNames={"request_id","cityId"})})
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class RequestCityId{
#GenratedValue(strategy=SEQUENCE, generator="seq_req_city_id")
#SequenceGenerator(name="seq_req_city_id", allocationSize=1)
#Column(name="rc_id")
#Id
long id;
#ManyToOne
#JoinColumn(name="request_id")
Request request;
String cityId;
String status
}
Existing table
#Entity(name="request")
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class Request{
String frequency
#GenratedValue(strategy=SEQUENCE, generator="seq_req_d")
#SequenceGenerator(name="seq_req_id", allocationSize=1)
#Column(name="request_id")
#Id
long id;
#OneToMany(cascade={ PERSIST, MERGE}, mappedBy="request", fetch=EAGER)
Set<RequestCityId> requestCityIds;
}
but when I am trying to insert into my new table I see my hibernate query gets stuck and just gets timed out after sometime, I am not sure what I am doing wrong here? If I just kep cascade type MERGE then getting
Hibernate Error: a different object with the same identifier value was already associated with the session

First you should create an getters and setters method to each entity.
Request Class
Request City Id Class
this code creates the tables and also saves the data into the table.

Using #Data in entity classes in not recommended because it may cause some problems with jpa as mentioned here.

Related

Document field as primary key not working

I have a "document" field that needs to be a primary key and must be unique, but every time I do a POST with the same document it updates the document and doesn't send a BAD_REQUEST
My entity:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"document"})})
public class Cliente {
#Id
#Column(unique=true, updatable = false)
#NotBlank #NotNull
private String document;
#NotBlank
private String name;
#NotNull
private LocalDateTime date;
}
When I try to make a new POST with the same document it just updates what is saved in the database.
"Hibernate: update client set date=?, name=? where document=?"
The problem is that Spring Data JPA, when you call Repository#save, assumes that you want to update an existing entity when the passed in entity object has the id attribute set. You will have to inject a EntityManager in your code and instead call EntityManager#persist if you want to make sure that Hibernate tries to do an insert, in which case you'd get a constraint violation exception, just as you expect.

JPA Entity class which is not mapped to any table

I am using a entity class for mixing two/three table columns in one entity to hold an outcome of SYS_REFCURSOR in oracle
This allows me to have single class which is not mapped to any table but it still is an Entity
#Data
#Entity
#NoArgsConstructor
class EmployeeDetails {
#Id
#Column("emp_id")
String empId;
#Column("job_name")
String jobName;
#Column("dept_name")
String deptName;
//Future requirement
//String updatedBy
}
Now I have an additional requirement, to add who last modified the employee table, I don't want modify the procedure now, the procedure is being re-used in another background procedure and batch jobs.
My question is, is it possible to use #ManyToOne on this class which is obviously not mapped to any table
If not how do avoid manually looping a child array list, is there a ready made option in JPA or spring boot to achieve that.
Or what will be the smartest/recommended way to bring the below Entity into this class
#Data
#Entity
#NoArgsConstructor
#Table(name="app_users")
class AppUsers {
#Id
#Column(name="user_id")
String userId;
#Column
String userName;
}
#Transient, check how this annotation works it will resolve the issue, you need to understand working of #Transient
My spring boot 2.6.2 EntityManager code is as follows
q = em.createStoredProcedureQuery("MY_PROC",EmployeeDetails.class);
q.registerStoredProcedureParameter("OUT_REFC", void.class, ParameterMode.REF_CURSOR);
q.execute();
q.getResultList()
I have modified my class EmployeeDetails as below
#Data
#Entity
#NoArgsConstructor
class EmployeeDetails {
#Id
#Column("emp_id")
String empId;
#Column("job_name")
String jobName;
#Column("dept_name")
String deptName;
#OneToOne
#JoinColumn(
name="user_id",
referencedColumnName="emp_id",
insertable=false,
updatable=false,
nullable=true
)
AppUsers updatedBy;
}
The log prints Hibernate two times one after one as below, first it calls the proc and then it calls the select query, so, I did not wrote that SQL myself, the JPA layer is taking care of it
Hibernate:
{call MY_PROC(?)}
Hibernate:
select
...
...
from app_users
where user_id=?
so, my expectation achieved and I am getting the values

CRUDRepository findBy foreign key id causing exception: Unable to locate Attribute with the the given name [classroomId] on this ManagedType

I am getting an exception when creating a custom findBy method by a foreign key.
Entity class:
#Entity
#Getter
#Setter
public class Thread {
private #Id #GeneratedValue Long id;
private String subject;
#ManyToOne(fetch = FetchType.LAZY)
#JsonIgnore
private Classroom classroom;
protected Thread() {}
public Long getClassroomId() {
return this.classroom.getId();
}
}
ThreadRepository class:
public interface ThreadRepository extends CrudRepository<Thread, Long> {
List<Thread> findByClassroomId(Long id);
}
I get the exception:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [classroomId] on this ManagedType [com.futurerprood.unicycleservice.entity.threads.Thread]
But the exception goes away if I remove the getClassroomId() in the Thread class. I have this function so that the json serialization will pick up only the classroom id instead of the whole classroom object in an endpoint response.
Why is this function causing the foreign key unable to be found?
You can do one of the following:
Provide the query to the repository method
#Query("select e from Thread t join t.classroom c where c.id = :id")
List<Thread> findByClassroomId(Long id);
Rename the repository method
List<Event> findByClassroom_Id(Long id);
Update
Explanation as to why these two are working
First, have a look at https://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/htmlsingle/#d0e391 and understand how property traversal based on method name happens in Spring data JPA in order to generate the query and how ambiguity resolution is recommended.
In the first one, we tell spring data, it does not need to do property traversal to generate the JPA query as we are giving the query so it does not get any ambiguity.
In the second, as recommended in the reference, we are resolving the ambiguity for Spring Data JPA by telling it to go to Classroom object first. But as #crizzis pointed out under the question comment, Spring data should have treated it as ambiguity in the first place

OneToOne Association In JPA not working using Spring boot and spring data JPA

I am trying to implement the OneToOne association in JPA and trying to join two tables using spring boot and spring data JPA. I created one spring boot microservice and implemented the one to one association in my model. But when I am running code I am getting the following error ,
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElement
Here My First model class Users.java is like following,
#Entity
#Table(name = "users")
public class Users implements Serializable {
private static final long serialVersionUID = 9178661439383356177L;
#Id
#Column(name="user_id")
public Integer userId;
#Column(name="username")
public String username;
#Column(name="password")
public String password;
}
And I am testing association by controller using following code,
#GetMapping("/load")
public Users load() {
return (Users) userObj.findAll();
}
Can anyone help to resolve this association issue please ?
This is wrong.
#OneToOne(mappedBy="nuserId")
public Set<UserRoleMapping> roleUserRoleMappingMappingJoin;
}
OneToOne means only one object..right?
See this for mappings understandings.
https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/collections.html#collections-persistent
Annotation #OneToOne defines a single-valued association to another entity, and in your case you associate a user to a Set of UserRoleMapping instead of associating it with a single object of that class. Use #ManyToOne annotation
Actually the exception refers to an invalid #OneToMany, #ManyToMany or #CollectionOfElement mapping
and this can only be
#OneToMany()
#JoinColumn(name="nuser_id" , referencedColumnName="nuserId")
public Users nuserId;
If the #OneToMany relation is valid change this at first to
#OneToMany()
#JoinColumn(name="nuser_id" , referencedColumnName="nuserId")
public List<Users> users;
If the #OneToMany relation is NOT valid change this to
#OneToOne()
#JoinColumn(name="nuser_id" , referencedColumnName="nuserId")
public Users users;

JPA Many to many unidirectional

I use spring data jpa and i try to do a many to many unidirectional relation.
#Entity
public class Appartment {
...
#ManyToMany
private List<AppartmentFeatureOption> featureOption;
}
#Entity
public class AppartmentFeatureOption {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long appartmentFeatureOptionId;
private String name;
private BigDecimal value;
}
My database is created at run time, but i get this error
org.hibernate.DuplicateMappingException: Same physical table name [appartment_feature_option] references several logical table names: [AppartmentFeatureOption], [Appartment_AppartmentFeatureOption]
Any idea?
Edit with this code that work
#ManyToMany
#JoinTable(name="appartment_feautre_option_appartment", joinColumns=#JoinColumn(name="appartment_id"), inverseJoinColumns=#JoinColumn(name="appartment_feautre_option_id"))
private List<AppartmentFeatureOption> featureOption;
Is this is actually your real code, maybe the issue is that you are using a ManyToMany relationship between Appartment and AppartmentFeatureOption whereas there is no link to Appartment in the AppartmentFeatureOption.
From my understanding for one Appartment you want to have several AppartmentFeatureOption, which is a OneToMany relationship.

Resources