Haha, Agree, It need to be done more smoothly :)
They are two framework, not one framework, it tried my best but it is impossible to find the smooth solution. I hope the ORM part of my framework can be merged into hibernate in the future if you can accept it.(The reason why I did it like this is the actual work is larger than my image, when I decide to do it in 2008, my goal of ORM part very small, but now, it's so huge)
Then I show the most important functionalities and show how did I implement them.
(1) ObjectModel4JPA, it can manage the bidirectional associations of JPA entities as powerful as ObjectModel4Java(User modification of one side can trigger an event to notify and change the other side automatically and implicitly).
(a) Use org.babyfish.hibernate.cfg.Configuration.processPersistentClasses() to replace the Hibernate Collection Type, the collection property is collection wrapper chain with 3 layers. +-Dynamically generated derived class that extends the collection under the package "org.babyfish.hibernate.association"(For bidirectional association managment) | \----+-Persistent MA Collection under the package "org.babyfish.hibernate.collection", Replace hibernate lazy collections, When the inverse collection is lazy, the modification implemented by fake mode, but the modifcation event will still be triggered. | \------MA Collection under the package "org.babyfish.collection", The Java part of this framework, support Unstable Collection Elements, Event Trigger and Bubble event (b) Use org.babyfish.hibernate.proxy.FrozenLazyInitializerImpl to replace the javassist Handler of Hibernate Proxy to let it can trigger even if it's lazy.
That's why the powerful functionalities of ObjectModel4Java can also be used on JPA Entity class too.
(2) QueryPath: For TypedQueryPath, it is created by the programmer via the generated source code. Be different with JPA static metadata model, the generated source code of TypedQueryPath dose not use the IOC, so it dose not depend on Hibernate injection, and it can be used wherever and whenever, eg: Hibernate is not started; In the bussiness logic layer or UI layer; Another remote machine that does not run Hibernate. For NonTypedQueryPath(Often created by javascript of UI layer), use the embeded query path compiler(babyfish-entity/src/main/antlr4/..../QueryPath.g4) to compile it.
Then org.babyfish.hibernate.hql.XQueryTranslatorImpl parses and changes the byte code of org.hibernate.hql.internal.ast.QueryTranslatorImpl to change the logic of HQL compiler, changes the HQL AST to apply query paths to add dynamic association fetches and dynamic order, then changes the SQL AST to do final optimization, finally uses batch query to load the fetched scalars(This progress it very complex, it uses org.babyfish.lang.reflect.asm.ClassEnhancer which is a powerful bytecode hacker, it can create derived class from a super class, and rewrite the private, final or static methods of super class).
Fewest demos that can demonstrate my solution as fast as possible: (A) Unstable Collections Element: babyfishdemo-macollections/src/test/java/org/babyfishdemo/xcollection/uce/UnstableCollectionElementsTest.java(This is very important to ORM, because ORM entities are often unstable) (B) Bubble Event: babyfishdemo-macollection/src/test/java/org/babyfishdemo/macollection/bubble/SimpleBubbleEventTest.java(Java Collection Framework is more complex than the collection of other langugages, ObjectModel is impossible to be implmeneted without bubble event) (C) ObjectModel4Java: babyfishdemo-om4java(babyfishdemo-om4-jpa only shows how to inject ObjectModel into JPA entity by byte code instrument, but does not show what the ObjectModel is) (D) QueryPath: babyfishdemo-spring/src/test/java/org/babyfishdemo/spring/dal/QueryPathTest(In real project, it can resolve problems very fast)
|