Persist entity OneToMany Relationship - java

I have a probléme when i want to persist 2 objet in database
In Request class:
#OneToMany(cascade = CascadeType.PERSIST, mappedBy = "request")
private List documents;
In Document class:
#JoinColumn( referencedColumnName = "ID_REQUEST")
#ManyToOne
Request request
the problem is that when I add request the I find that the 2 object are persisted but in the table Document lD_REQUEST IS ALWAYS NULL
THANK YOU IN ADVANCE and sorry for my English

You need to declare what is the column on the document table that contains the request Id:
#JoinColumn(name = "PARENT_REQUEST")
where PARENT_REQUEST is the name of the column on your Document table

While persisting new data into the database, you've probably added documents to Request's list but forgot to set Request's object to all of your documents on the other side.
Check that you did both things (the following is the example):
Request request = new Request();
//initialization of request
for (...) { //iterate over all document candidates
Document document = new Document();
//initialization of document
document.setRequest(request); //check this!
request.getDocuments().add(document);
}
Also, it seems that you don't have a not-null constraint on ID_REQUEST column. Add this so you won't have this broken data with nullable ID_REQUEST field in the future (constraint violation exception will be raised instead in this kind of situations).

Related

Creating an entity with a ManyToOne annotation

I'm creating an entity which has a ManyToOne relation to another one, it being multiple customers can belong to one company. Now I have my Customer entity defined as follows:
#Entity
#Table(name = "Customers")
data class Customer(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
var customerId: Long? = null,
var firstName: String,
var lastName: String,
var gender: String,
#Column(insertable = false, updatable = false)
var companyId: Long,
#ManyToOne(targetEntity = Company::class, fetch = FetchType.LAZY)
#JoinColumn(name = "companyId", referencedColumnName = "companyId")
var company: Company? = null,
var profilePicture: String,
var email: String,
var phone: String,
var birthDay: String,
var bio: String,
var notifyByPhone: Boolean,
var notifyByEmail: Boolean,
var notifyBySms: Boolean,
#UpdateTimestamp
var updatedAt: LocalDateTime,
#CreationTimestamp
var createdAt: LocalDateTime
)
I use the following function from CustomerResource as an endpoint to persist the Customer:
#Transactional
#POST
fun post(#Valid entity: Customer): Response = try {
repository.persist(entity)
created(entity)
} catch (exc: Exception) {
serverError(exc)
}
Using Postman, I use the following JSON object to fire a request to the endpoint:
{
"firstName": "Ricardo",
"lastName": "de Vries",
"gender": "male",
"companyId": "200",
"profilePicture": "test",
"email": "mail#gmail.com",
"phone": "0612536263",
"birthDay": "28-12-1995",
"bio": "Nothing",
"notifyByPhone": true,
"notifyByEmail": true,
"notifyBySms": true
}
I have a property called "company" which is being mapped to the Company the user belongs to, based on the companyId. I have a separate companyId field which is being mapped to the companyId field in the database.
When I want to create a new Customer, I'm including the companyId in the request. This succeeds and the Customer is being successfully created.
Now when I try to fetch that specific customer, I get the following
error: "org.hibernate.PropertyAccessException: Null value was assigned to a property [class org.acme.domains.core.models.entities.Customer.companyId] of primitive type setter of org.acme.domains.core.models.entities.Customer.companyId".
I don't really get why this error occurs. I would think that the Company which belongs to the Customer gets added afterwards whenever I fetch a specific Customer.
Does anybody know how to be able to add an entity this way?
Do you have the proper getter and setters generated? It seems like the first request is failing to set the fields properly. I suggest you put a breakpoint to the controller that creates your customer and check if the field is being set like it should. Maybe you are passing the data in a wrong format etc. I can't say that from this information but you should debug that.
You can also put #NotNull validation on your fields to see if it fails to be set in object creation.
You have mapped companyId as not insertable and not updatable, so it won't appear in the query.
Try change it to:
#Column(insertable = true, updatable = true)
Long companyId
What's happening, I think, it's that Hibernate ORM is creating the insert query with all the other values, except for this one.
I would recommend enabling the log to check. You can do it in the configuration by setting:
hibernate.show_sql = true
hibernate.format_sql = true

ERROR: duplicate key value violates unique constraint error JPA spring boot

I have two tables notification and message.
Message.java
...
...
#Table(name = "message",
uniqueConstraints = {#UniqueConstraint(name = "UniqueMessage",
columnNames = { "message_id" })})
public class Message implements Serializable {
#Id
#Column(name = “message_id")
private int messageId;
#Column(name = "description")
private String description;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "start_time")
private Date startTime;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "end_time")
private Date endTime;
#PrePersist
#PreUpdate
public void generateMessageId(){
this.messageId = Math.abs(Objects.hash(this.getDescription(),
this.getStartTime().getTime() / 1000));
}
My use case is -- I will be creating a message with certain description and start time. If I get same message again, I should be able to update the endTime. MessageId is calculated separately under method generateMessageId as this will act as an identifier to find if message has already been saved. If yes, I will update the message. It works well for first message but when I try to save again with updated endTime, I get
ERROR: duplicate key value violates unique constraint “message_pkey”
Steps:
I tried:
Message m1 = new Message();
m1.setDescription(“fake”);
m1.setStartTime(“2022-01-03T12:05:00”)
messageRepository.save(m1);
This works well. I can see a row in database with
Message_id description start_time end_time
46536723 fake 2022-01-03T12:05:00 null
Message m2 = new Message();
m2.setDescription(“fake”);
m2.setStartTime(“2022-01-03T12:05:00”);
m2.setEndTime(“2022-01-05T12:00:00)
messageRepository.save(m2);
I get ERROR: duplicate key value violates unique constraint error.
Isn’t jpa should find the existing id and do an update to the row instead of inserting?
Please suggest if this method looks like a work-around.
You are trying to update the message endTime, First time, it works because there is no entry of that message now when you are trying to update but you are not setting the id by default id is zero and if Id is zero it will try to save the message instead of updating.
For resolving this issue you can check (by finding the message by message because the message is unique) if that message is present then update the endTime.

Disable warning "entity was modified, but it won't be updated because the property is immutable" when saving entity with fields marked updatable=false

I have some fields marked with #Column(name = "column1", updatable = false) in entities in jpa repository, and it works as intended but when saving the entity a warning message like this is show:
2020-04-23 18:48:34.358 WARN 1112 --- [nio-8080-exec-6] o.h.p.entity.AbstractEntityPersister : HHH000502: The [column1] property of the [com.nodobanka.core.data.model.Entity1] entity was modified, but it won't be updated because the property is immutable.
I just want to know How Can I stop this warning from printing in log?.
You can set logging level for org.hibernate.persister.entity package to ERROR. That way it'll only display logs with ERROR and FATAL levels.
You can do this in Spring by adding following line in application.properties file:
logging.level.org.hibernate.persister.entity: ERROR
You can use relation for updates (instead of FK field).
Kotlin example:
data class ... (
...
) {
#Column(name = "market_id", nullable = false, insertable = false, updatable = false)
var marketId: Long = 0
/**
* This field is used for updates instead of [marketId] to avoid warning about immutability
*/
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "market_id")
lateinit var market: NiceHashMarket
}
...
entity.market = Market(...)

Hibernate not deleting/updating one to many

I am trying to learn how to work with hibernate, and until now i thought i was doing ok...
The problem is, i have a one to many relationship that i can't update/delete.
My DB is pretty basic, i have a ClientsBasic that has a one to many relationship with IndirectClients (which simply has a ClientsBasic ID and a URL, both keys because you can have for the same ID lots of URLs)
ClientBasic:
#OneToMany(fetch = FetchType.EAGER, mappedBy = "clientsBasic", cascade=CascadeType.ALL)
public List<IndirectClients> getIndirectClients() {
return this.indirectClients;
}
public void setIndirectClients(List<IndirectClients> indirectClients) {
// this.indirectClients = indirectClients;
this.indirectClients.clear();
this.indirectClients.addAll(indirectClients);
}
ClientDao:
public ClientsBasic save(ClientsBasic client) throws HibernateException {
Transaction tx = null;
tx = session.beginTransaction();
session.saveOrUpdate(client);
tx.commit();
log.info("Client saved with id: " + client.getClientId());
return client;
}
Now if i try to delete ClientsBasic, it will delete both ClientsBasic and all related indirectClients, so its working as expected, but if i simply try to update/delete and entry in indirectClients it doesn't work.
Example:
I create a new Client
ClientsBasic cb = new ClientsBasic("company_1", 1234, "company_1#email.com");
cbDao.save(cb);
And then a new Indirect Client
List<IndirectClients> indirectClientsSet= new ArrayList<IndirectClients>();
indirectClientsSet.add(new IndirectClients(new IndirectClientsId(cb.getClientId(), "www.url.test_1.com"), cb));
cb.setIndirectClients(indirectClientsSet);
cbDao.save(cb);
Now if i try to change the url like this
ClientsBasic cb = cbDao.findClientById(1);
List<IndirectClients> indC = cb.getIndirectClients();
indC.get(0).getId().setUrl("TEST");
cb.setIndirectClients(indC);
cbDao.save(cb);
no changes are made in the DB.
Can someone please help me?
Thank you.
If your IndirectClients is defined as an Entity it has its own life cycle, meaning you have to persist/delete instances separately from their ClientBasic parent.
If you want a scenario where all children are managed through their parent relation, consider using ElementCollection.
See also JPA: When to choose Multivalued Association vs. Element Collection Mapping

How do I get a Datastore Entity by its unique ID if I know the ID?

This is how I created the entities
Key reviewsKey = KeyFactory.createKey("Reviews", "Reviews");
Entity reviewEntity = new Entity("aReview", reviewsKey);
....
This is how I am trying to get an entity by its key
Key key = KeyFactory.createKey("Reviews", "Reviews");
Entity reviewEntity = datastore.get(key.getChild("aReview", reviewId));
....
I know there is an entity with key = 14 but i keep getting an exception that there is no entity found
Reviews("Reviews")/aReview("14")
What am I doing wrong?
The issue was it was looking for a string ID when it should have been Long
I have parsed it to Long and it works now.
Key key = KeyFactory.createKey("Reviews", "Reviews");
Entity reviewEntity = datastore.get(key.getChild("aReview", Long.parseLong(reviewId)));

Categories

Resources