How to get current modified record in custom entity listener in envers - hibernate-envers

I created a Listener CustomRevisionEntityListener which implements RevisionListener and CustomRevisionEntity(added column allocateTo) which extends DefaultRevisionEntity.
I annotated a class Employee with #Audited. Employee class has a field isAvailable.
My requirement is if user changes Employee -> isAvailable value to true, i need to update allocated column in CustomRevisionEntity record.
How to get modified employee model / employee_aud record in CustomRevisionEntityListener ?

I think you should use the "entity tracking revision listener". This allows you to be notified when an entity is changed. See here: http://docs.jboss.org/hibernate/core/4.0/devguide/en-US/html/ch15.html#envers-tracking-modified-entities-revchanges

Extended hibernate 'post-update' event, so that we can fetch dirtyProperties of entity 'Employee' and add the properties along with old and new values to CustomRevisionEntity.

Related

How to ignore a JPA ManyToOne property with null value on merge after JAXB deserialization?

Example use case:
class Address {
#XMLTransient
#ManyToOne(cascade={})
private Person person;
}
In my use case Address is serialized to XML via JAXB, modified in another system, deserialized from XML to a detached JPA entity and then merged back to db (em.merge(address)). As the Person property is marked #XMLTransient it is restored from XML with null.
As all Address' have a database entry and could be identified by there Id I'd like merge to ignore the Person property and just keep the database value for the relation (this has nothing to do with cascade).
Is there a way to tell JPA to ignore the Person property on merge or would I have to use an #XMLAdapter to set the property with the corresponding Person object before merge (btw I also use optimistic locking with #Version on all entities).
Any hints?
Miguel
It sounds like you don't want this relation to be updated by JPA at all, upon a merge. Is that correct? If so, have you tried setting updatable=false on the #ManyToOne?

Entity Framework inserting row with composite key

I am using Entity Framework 4.3.1 and I am trying to insert a new record into the table my ProductVersion entity is based on.
The ProductVersion entity has 2 properties that make up a composite primary key for the table called ProductId and ProductOrdinal.
Whenever someone updates a product entry I am creating and passing a ProductVersion entity back to my repository, incrementing the ProductOrdinal property, and attempting to add the entity to the context and save it.
I keep getting the following error:
The property 'ProductOrdinal' is part of the object's key information and cannot be modified.
Neither of the columns that make up the key are autonumbering and I have annotated the properties in my POCO with the following:
[Key, Column("PROD_Ordinal", Order=2), DatabaseGenerated(DatabaseGeneratedOption.None)]
public long ProductOrdinal { get; set; }
Marc_S was exactly right in his comment as to why this was not working.
From the exception and your description it seems that you are incrementing the 'ProductOrdinal' property on the existing 'ProductVersion' instance and trying to save it. What you probably want to do is create a new instance of 'ProductVersion' from the existing instance and increment the 'ProductOrdinal' property and save the new instance.

Entity framework Association in conceptual model for one to many relationship

I have two entity CUSTOMER and ORDER..there is one to many relation from CUSTOMER to ORDER where CustomerID is primary key for customer and foreign key in ORDER..now I want to add customer name property from CUSTOMER entity in ORDER entity...I have copied this property and paste it in ORDER table and have added CUSTOMER table and map this property to the CUSTOMER table's same property..but when i trying to validate it vs giving me a Error that is
3024: Problem in mapping fragments starting at line 239:Must specify
mapping for all key properties (ORDER.OrderID) of the EntitySet ORDER
That is not possible in mapping. You cannot add property from Customer table into Order entity this way. Mapping properties from multiple tables to the same entity has very strict rules and it is not possible for this case.
You can expose customer's name in your Order class without defining it in the mapping. Create partial part of Order class and add custom computed property (non mapped):
public partial class Order
{
public string CustomerName
{
get
{
// Customer is navigation property to Customer entity
return Customer.Name;
}
}
}
This will require loading Customer with your Order (eager loading) or using lazy loading. Also this property cannot be used in Linq-to-entities queries.

Entity Framework Code First - Table Per Type Inheritance - Insertion Issue?

I'm having an issue inserting an instance of a subclass that inherits from a base class.
Consider the following code snippets from these POCOs:
public abstract class EntityBase<T>
{
private T _id;
[Key]
public T ID
{
// get and set details ommitted.
}
}
public abstract class PersonBase<T> : EntityBase<T>
{
// Details ommited.
}
public class Applicant : PersonBase<int>
{
// Details ommitted for brevity.
}
public class Employee : Applicant {}
Pretty standard inheritance right now. In our system, when an applicant finally becomes an employee, we collect extra data. If not hired, they remain an applicant with a limited set of information.
Now consider the fluent API that sets up the table-per-type inheritance model:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Set up table per type object mapping for the Visitor Hierarchy.
modelBuilder.Entity<Employee>().ToTable("Employees");
}
So far, so good...
If I look at the database this creates, I have a table named Applicants with an Id column of type int, auto-incrementing ID and I have an Employees table with an ID field as the primary key (non auto incrementing).
Basically, the ID field in the Employees table is a foreign key to the Applicants table.
This is what I want. I don't want a record into the Employees table corresponding to the Applicants table until they actually become an Employee.
The problem comes when I try to insert an Employee which comes down to this code:
public void PersistCreationOf(T entity)
{
DataContextFactory.GetDataContext().Set(typeof(T)).Add(entity);
}
The problem: It inserts a brand new applicant and Employee. I hooked it up to the Sql Profiler and looked at both insert queries that come down.
I want to just insert the Employee record with the ID it already has (the foreign key from the Visitors table).
I understand by default it needs to this: Obviously if you create a subclass and insert it, it needs to insert into both tables.
My question is is possible to tell the Framework - the base table already has information - just insert into the child table?
Thanks in advance!
Aside from sending raw SQL commands to insert the Employee minus Applicant properties fragment into the Employees table I believe it's impossible. You can either update or insert an entity. What you want is basically to update the base part of the Employee (or do nothing if nothing changed) and insert the derived part which is not possible.
Imagine what an ORM does: It maps key identities in the database to object identities in memory. Even in memory you couldn't achieve what you want: If you have an object in memory which is a Applicant, it is always an applicant. You cannot magically "upgrade" it to an Employee. You would have to create a new object of type Employee, copy the properties of the Applicant into the base properties of your new Employee and then delete the Applicant. The result is a new object with a new object identity.
I think you have to follow the same procedure in EF. Your Employee will be a new entity with new rows in both Applicant and Employee table and you need to delete the old Applicant. If you have autogenerated keys it will be a new identity with a new ID. (If you hadn't autogenerated keys you could supply the old ID again after deleting the old Applicant, thus "faking" an unchanged identity.) This will of course create big potential trouble if you have references to the old applicant with FK constraints.
Perhaps inheritance is not optimal for this scenario to "upgrade" an applicant into an employee. An optional navigation property (1-to-0...1 relationship) inside of the Applicant which refers to another entity containing the additional properties which make the applicant an employee would solve the problem. This navigation property could be set or not, letting you distinguish between an applicant and applicant which is also an employee. And you would not need to delete and change the ID of the applicant when you make it an employee.
(As said, "I believe". Maybe there is a hidden way, I didn't see.)

Entity framework and pure POCO update

How do I do an update on a pure POCO object using entity framework 4?
Lets say I change the person's first name and call the repository in this manner:
public User Update(User user)
{
//User originalUser = GetUser(user.UserId);
//Is there a way to update the values that are only changed?
context.Users.Attach(user);
context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
return user;
}
I dont want null values to update the database to null. For eg. Suppose I have LastName as a property but when passing the object to the update function, it was null. Am I going to have to get the originalUser and then update each property accordingly?
"update each property accordingly?"
No, you can use,
context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entity);
// this will gives you the entity present in db and after that I suggest to write your code to change the state and save.
Also suggest you to read this
for more info on tracking changes in POCO entities