I've just run into a problem, where I'm trying to select (repo.findById(id)) an object from the database using it's id, while it's being updated (Hibernate's onPreUpdate and onPostUpdate methods in PreUpdateEventListener and PostUpdateEventListener interfaces), but it's throwing a NullPointerException for me.
Perhaps it's easier if I explain it this way:
I have an object with status "PENDING", if it's being changed to "CONFIRMED", I want to check what the previous status was in the onPreUpdate method by doing this:
#Override
public boolean onPreUpdate(PreUpdateEvent preUpdateEvent)
{
final Object entity = preUpdateEvent.getEntity();
if (entity instanceof Status)
{
Status status = (Status) entity;
//Method below throws NullPointerException
Status statusFromRepo = statusRepo.findByStatusId(status.getStatusId());
}
return false;
}
But since statusRepo is already updating this object in the database, am I not able to do anything to get the object BEFORE it's updated? PreUpdateEvent contains the already "updated" version which is going to be saved in the database.
Related
I made a litte reactive REST service with quarkus, mutiny and panache and discovered some odd behaviour. Everything works as expected when I update an instance with an id that is in the database. But when I change the id to something not existent, I would expect that a failure is raised. Instead I get nothing, and just work on the item that i provided.
#ApplicationScoped
class MyService #Inject constructor(private val myRepository: MyRepository) {
fun update(myEntity: MyEntity): Uni<UUID> {
return myRepository.update(myEntity)
.onItem()
.transform { item -> item.uuid }
}
fun persist(myEntity: MyEntity): Uni<UUID> {
return myRepository.persist(myEntity).onItem().transform { item -> item.uuid }
}
}
class MyEntity {
#BsonId
var uuid: UUID? = null
...
}
So if I persist my first entity with uuid A, the entity is inserted and i return uuid A to the caller. When I call update with uuid A, the entity is updated, and A is returned. But when I call update with an entity with the non existent uuid B, nothing happens in the DB, but i still will get my uuid B without any failure an return it.
Can anybody tell me what I am doing wrong, or how I can get the information if an update was done or not?
Edit:
And I also dont understand where this item comes from. My call runs in this method:
So as I see, the retrieved item is even discarded and null is returned. So how can my updateCall bring up any item?
I have a Short Question:
Last Save is working(Last Save will be Update).
But First Save is not working.(First Save will be Insert)
I can't insert this way, how is it possible?
#GetMapping(value = "/delete/{id}")
public String delete(#PathVariable BigInteger id, Model model) {
try {
Group group = groupService.findById(id);
group.setId(null);
group.isLog(true);
// This Save will be Insert Data
groupService.save(group);
group = groupService.findById(id);
group.isLog(true);
//This Save will be Update Data
groupService.save(group);
return "redirect:/accountsGroup/";
} catch (Exception ex) {
return "masters/accountsInfo/groups/index";
}
}
You can't just set the ID null.
The entity is in a managed state and will not be new just because you set the ID to null.
The proper way would be to clone the entity state in a new instance.
You could also try to detach the entity (EntityManager.detach) and then set the ID to null. Maybe it will insert a new row. But as I said this is not the way you should do that.
Read more about entity states here: https://vladmihalcea.com/a-beginners-guide-to-jpa-hibernate-entity-state-transitions/
I'm facing a singular problem...
I need to update an entity, but i don't know when it is really updated
My method is
#Override
#Transactional(isolation = Isolation.SERIALIZABLE)
public void lightOn(int idInterruttore) {
Interruttore interruttore = dao.findById(idInterruttore);
String inputPin = interruttore.getInputPin();
String pinName = interruttore.getRelePin();
GpioController gpio = interruttore.getGpio();
GpioPinDigitalOutput rele = gpio.provisionDigitalOutputPin(RaspiPin.getPinByName(pinName));
try {
DateTime date = new DateTime();
Date now = date.toDate();
int i = 1;
while (getInput(inputPin, gpio) != 1) {
if(i > 1){
logger.debug(String.format("Try n %s", i));
}
pushButton(rele);
Thread.sleep(1000);
i++;
}
dao.updateInterruttore(idInterruttore, now, true);
} catch (GpioPinExistsException | InterruptedException gpe) {
logger.error("GPIO giĆ esistente", gpe);
} finally {
gpio.unprovisionPin(rele);
}
logger.debug(String.format("After the update status should be true and it's %s",
interruttore.isStato()));
}
updateInterruttore is (i used this form to be sure to call the commit after the update... I have the lock Option because multiple call can be done to this method but only the first must update
#Override
public void updateInterruttore(int idInterruttore, Date dateTime, boolean stato) {
Session session = getSession();
Transaction tx = session.beginTransaction();
String update = "update Interruttore i set i.dateTime = :dateTime, i.stato = :stato where idInterruttore = :idInterruttore";
session.createQuery(update).setTimestamp("dateTime", dateTime).setBoolean("stato", stato)
.setInteger("idInterruttore", idInterruttore).setLockOptions(LockOptions.UPGRADE).executeUpdate();
tx.commit();
}
}
Well... when I update the log says me:
After the update status should be true and it's false
This happens only the first time I call the method, the second time interruttore.isStato is correctly true.
Why this happens?
This happens because you're updating the database directly with the update statement. Hibernate does not update automatically an already loaded entity in this case. If you reload the entity after the call to dao.updateInterruttore you should get the updated data.
Two notes:
1) You are using a query to apply the update. In that case, Hibernate will no update the entity that is in the session. Unless you update the entity itself and call session.save(interruttore), then the entity will not be updated. (But the update shows up in the DB.) Furthermore, I don't understand why you just don't update the entity and save it via session.save().
2) You are annotating the service method with #Transactional. (Assuming that's Spring annotation) If you use JTA, your tx.commit() will have no effect. But once the method completes, your transaction is committed. (or rolled back if the method throws an exception) If you are not using JTA, then get rid of #Transactional and manage transaction in your DAO method, as you are doing. But that's considered bad practice.
Here in the following code when I invoke discoverAsync method by passing a node which is already in table, it should check that node id is exist in a table and update the other field in that row. But actually it is not happening, hiberbate is just selecting but not updating.
What my point of view is that we can not retrieve and update the same row at a same time in a same transaction. Please correct me if wrong.
Here is the code:
public Node discoverAsync(Node node) throws Exception {
if(isNodeIdEqual(node))
super.saveOrUpdate(node);
else
// TODO Raise Exception in case no node is available for discovery.
return node;
}
public boolean isNodeIdEqual(Node node){
String id = node.getId();
String retrievedId = getByKey(id).getId();
return id.equals(retrievedId);
}
You don't need to check using your method isNodeIdEqual. Hibernate's saveOrUpdate will do that for you. If the record with a particular key is not found, it will save, if it found it will update by the key
I have an Entity class in which I put uniqueconstraint annotation
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"staffRecord_id", "defaultLabel_id","company_id","keyCode"})})
public class AllowanceDeduction implements Serializable{
---
What I have noticed that is when I try to save on the table
using
if (allowanceDeduction.getId() == null) {
this.entityManager.persist(allowanceDeduction);
} else {
this.entityManager.merge(allowanceDeduction);
}
when the save or update fails due to a unique constraint. Isn't it only supposed to fail when trying to save a new record that is identical to a record that already exist.
Why would it fail when trying to merge or update?
Please help needed
I can't say for sure but it looks like you're trying to persist a null id
if (allowanceDeduction.getId() == null) {
this.entityManager.persist(allowanceDeduction);
/* don't you need the id set to a non-null value in order to persist it? */
} else {