Programmatically extending Hibernate table/entity definitions in Spring, how?

I would like to know if there is a way —maybe with AOP— to extend table/entity definitions so that I can add functionality across the board that requires persistence.

Let me explain what I want to do with a concrete example. Let’s suppose we have a simple ecommerce system:

  • User
    • id
    • name
    • password
  • Item
    • id
    • name
    • price
    • stock
  • ShoppingCart
    • id
    • user_id
  • ShoppingCartItems
    • id
    • shopping_cart_id
    • item_id
  • Order
    • id
    • shopping_cart_id
  • Purchase
    • id
    • order_id
    • invoice_number

Now, let’s suppose that we think:

hey, wouldn’t it be great if we could add a field to timestamp all entities?

You would now know things like:

  • When a User registered
  • When an item was created
  • When a shopping cart was created
  • When an item was added to a shopping cart
  • When an order was placed
  • When was the order was processed and paid

Now you have another great idea:

What if there was a status field for all entities so I could soft-delete or archive items, etc.

And yet another idea:

What if there was a text field called meta to serialize unimportant data, but that could help adding functionality without painful database modifications.

There are solutions I can think of (meeting relational integrity requirement):

  1. Of course, you would need to go back, change your tables, modify your implementations so that when creating/updated you save the timestamp of then operation, same for status, same for meta.

  2. And a somewhat convoluted but very modular way. Create some sort of plugin, that creates a table that handles the field, and 1 pivot for each entity. And through events, associate the extended data to the existing entities accordingly.

But what if… you could just tell Hibernate to extend the table definitions programmatically at run time, and add the persistence behaviors through something like AOP to inject functionality.

I actually did the first thing (programmatically extending table definitions outside existing implementation) in Doctrine successfully once, but I’m just starting to learn Hibernate. OTOH, I’m just starting to learn Spring and know the basics on AOP, so at least in my mind it is feasible to intercept Hibernate’s configuration process where it understands table definitions.

So, is this possible with Spring and Hibernate?, how?, can you provide an example?

Addendum: The problem is that I need to do this more than once, and it could come from anywhere. AOP was my answer to the multiple inheritance problem since extending classes would be too constrained, however, in the past I did it with Events and worked just as fine… IIRC the problem is that I had to hack Doctrine in order to do this to fire an event at the time between when the model description was being converted from configuration files into actual models.

AOP is not a must, just an idea for an approach if such an event or dependency injection mechanism is not already in place. Another approach could be mixins, but I come back to AOP as probably the most elegant solution.

The main requirement here is to not modify the original model’s code.

Disclaimer: I’m not an expert on AOP but I’m fairly familiar to the concepts.

2

As far as I can tell, what you are describing can be trivially implemented with an Embeddable class and not need of AOP.

@Embeddable
class Audit {
  Timestamp created;
  String createdBy;
  String updatedBy;
}

Then you can simply add your embeddable object within your entities.

@Entity
class Order {
   @Embedded
   Audit audit;
}

Using inheritance, you might just as well make this available for a set of entities:

@MappedSuperClass
class MotherOfAllEntities {
   @Embedded
   Audit audit;
}

@Entity
class ChildClass extends MotherOfAllEntities {
}

If the information being added is just audit information, as you seem to suggest in your post you may consider using something like Hibernate Envers which seems to be an implementation of what you’re apparently suggesting with your question

@Entity
@Audited
class Order {
}

And Envers will make sure to store audit information about the entity in some other data structure.

Since Envers seem to be an implementation of something like what you want to do from scratch, you might just as well give it a look to their code and see how they did it, but yet again, if it is to implement what you described, to me it sounds like killing a fly with a bazooka.

1

Hibernate has events to which you can react using interceptors. Here’s an incomplete list of events:

  • onDelete
  • onSave
  • instantiate
  • afterTransactionCompletion

Take a look at org.hibernate.Interceptor to see complete list of events to which you can react using Interceptor.

Simplified example of classical usage is auditting interceptor which sets “lastmodified”:

public class AuditInterceptor extends EmptyInterceptor {
    @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        if (entity instanceof AuditedEntity) {
            int index = findElementIndex(propertyNames, "dateModified");

            if (index >= 0) {
                state[index] = new Date();

                return true; // entity has been modified
            }
        }

        return false; // entity was not modified
    }

    private int findElementIndex(String[] propertyNames, String element) {
        for (int i = 0; i < propertyNames.length; i++) {
            if (element.equals(propertyNames[i])) {
                return i;
            }
        }

        return -1;
    }
}

Interceptors might not be enough for your needs. Luckily Hibernate’s architecture is quite pluggable – most of the functionality consists of “Services”, resp. service implementations which implement service roles (interfaces). You can override default implementations with your custom ones, or even add totally new services. But this might be more involved and might break in future versions of Hibernate. I’d recommend to stick with interceptors as much as possible.

I have quite trouble understanding what your use case is. You do not come up with a question, you come up with a solution.

Your question seems to be about metadata and where to store it.

You would now know things like:

  • When a User registered
  • When an item was created
  • When a shopping cart was created
  • When an item was added to a shopping cart
  • When an order was placed
  • When was the order was processed and paid

Depending on the use case it makes perfectly sense to store the metadata alongside the business data. You have to change your database scheme accordingly.

I) The simple and straightforward usecase

From that it would be natural extending a BaseItem, which has such information like created, createdby, modified, modifiedby and adding some columns to other objects like lastseen on the user.
With that you are able to derive some questions from these values:

When an item was added to a shopping cart

When you have an order and an orderposition the created of the orderposition tells you, when the entry was added.

I do not see a reason to use AOP for this usecase.

II) The more advanced usecases of Datamining and Monitoring

II a) Monitoring

Let’s suppose we have a simple ecommerce system

Let’s suppose, you have indeed an eCommerce system and not only for the sake of the example, you might be interested in monitoring like AppDynamics or New Relic or something like that.

With such a sophisticated instrumentation, you are able to monitor each and every point of your application. I can not speak for New Relic, but I have used AppDynamics for myself. With AppDynamics, you could place Information Points, where you could track everytime when a method is called – e.g. orderSubmit.

When your usecase is more of tracking the systems behaviour in case of performance improvement or simple counters, that would be a simple way to go, without touching any code.

But the main point of such systems is providing health information for your application. and I would recommend it anyways if you run an eCommerce business. Downtime is loss of money.

II b) Data Mining

In case you are interested in metadata for datamining puroses IIa is the wrong road. Depending on the scale of metadata you want to gather, you should put it to a separate datastore.

As already mentioned, there are several ways to hook into your application:

  • simply edit the business code and add a simple methodcall to the external system.

Pro: It’s plain and simple. Everybody knows, what you are doing

Con: You litter your codebase

  • using AOP – like you suggested

Pro: It’s a sophisticated approach to deal with such cross cutting concerns. No existing code has to be touched

Con: It makes code for inexperienced coders hard to understand – things seem to happen magically.

  • Interceptors as already mentioned

Is something in between.

For simplicity and readability, I would go for the first solution despite the fact, that you have another kind of “logging”

P.S.: Nothing hinders you from doing I) and II) alltogether :]

Dont invent the wheel again!

Hibernate has Plug-ins, use them! You may be interrested in Enver and Auditing.

This is a example of what you are looking for:

AuditReader reader = AuditReaderFactory.get(entityManager);

Person person2_rev1 = reader.find(Person.class, person2.getId(), 1); 
                            // version 1 is from archive
assert person2_rev1.getAddress().equals(new Address("Grimmauld Place", 12));

Address address1_rev1 = reader.find(Address.class, address1.getId(), 1);
assert address1_rev1.getPersons().getSize() == 1;

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật