Recently, I started using Eclipse as my development environment. This is partly because it supports many of the platforms I use when I develop, partly because Eclipse is an outstanding representative of an open and extensible environment, and everyone can contribute to its development. I'm starting to look at some of the extensions that people have put forward. For example, I used a small plug-in called Xmlbuddy to work with XML files, which is useful. So, I started to wonder if anyone had written a plugin using Hibernate, and I did a lot of work on it recently when I wrote Developer's notebook. As a result, I understand that there are indeed some work in progress, and this article will explore one of the--hibernate Synchronizer.
Hibernate Synchronizer
So far, in the plugin I found, Hibernate Synchronizer was most interesting to me because it seemed to provide the best support for a mapping-centric workflow, and my Developer ' s notebook This workflow is used in a book. (Hibernate can be used for a variety of purposes, so check out the other plug-ins that are available, which will be more helpful if your environment requires other methods.) In fact, the Hibernate Synchronizer plug-in allows you to modify the mapping document without having to consider updating the Java code, which automatically updates the Java code in a very similar way to eclipse when you edit it. By creating a pair of classes for each mapped object, it is more advanced than the Hibernate built-in code generation tool. It "owns" a base class, and when you modify the mapping, it can override the base class at will. It also provides a subclass that extends the base class, and you can add business logic and other code to the subclass without having to worry about it disappearing under your nose.
Because you want to apply to the Hibernate mapping document-centric approach, Hibernate Synchronizer also includes a new editor component for Eclipse, which provides intelligent assistance and code completion for such documents. Good DTD-driven XML editors (such as the Xmlbuddy mentioned earlier) can implement some of these functions, but hibernate synchronizer use the understanding of document semantics to do better. It also provides a graphical view of the properties and relationships in a map, a "wizard" interface for creating new elements, and other similar benefits. And as mentioned earlier, in its default configuration, the editor automatically regenerates the data access class when the user edits the mapped document.
Hibernate Synchronizer has other functions as well. It adds a zone to the eclipse's new menu, provides wizards for creating hibernate configuration and mapping files, and adds context menu items to the package's resource manager and other appropriate locations, giving users easy access to related hibernate operations.
Well, now that there are enough abstract descriptions, it's time to start practicing! After all, you probably have an interest in this, or you won't be able to read this article. So, how do you install and use hibernate synchronizer?
installation
You can use the built-in Update manager for Eclipse to install hibernate synchronizer. This plug-in provides a separate update site for Eclipse 2.1 and for users of Eclipse 3, which is about to be released. Because I use Eclipse for mission-critical work, I'm still using the production version, which is 2.1. At the time I wrote this article, Eclipse 3 was already in the "Release Candidate" phase. When I came back from the JavaOne meeting this late summer, I wanted to be able to upgrade to the production version 3. (The main reason I mention this is to emphasize that the following guidelines were written based on Eclipse 2; in Eclipse 3, some commands and interfaces will certainly be different, so if you're ready to use them, make sure to add your own judgment as you follow these steps!) My impression is that hibernate synchronizer own
Installation Instructionsis written for Eclipse 3, which may help you. )
Start Eclipse and select Help-> Software Updates-> Update Manager to open Update Manager. After the install/update perspective is open, right-click in feature updates view (or control click (Control-click), and if you are using a single button mouse, select New-> Site Bookmark, as shown in Figure 1.
Figure 1. Add Hibernate Synchronizer plug-in site to update Manager
In the dialog box that appears, enter the URL of the plug-in version that you want. The URL you enter depends on your version of Eclipse:
- Eclipse 2.1:http://www.binamics.com/hibernatesync/eclipse2.1
- Eclipse 3:http://www.binamics.com/hibernatesync
You also need to specify a name for the new bookmark, "Hibernate synchronizer" is fine. Figure 2 shows a dialog box that includes all the necessary information in my Eclipse 2.1.2 environment.
Figure 2. Hibernate Synchronizer Plugin update site bookmarks
After you click Finish, the new bookmark appears in the feature updates view, as shown in Figure 3.
Figure 3. The Hibernate Synchronizer site is now available
To actually install the plug-in, click the triangular expansion symbol to the left of the bookmark, and then click the next triangle to expand the symbol to repeat the process until the plugin icon appears. When you click the icon, the Preview view is updated to show an interface that allows you to install the plugin, as shown in Figure 4.
Figure 4. Preparing to install Plug-ins
Click Install Now to actually install the plugin and let Eclipse lead you through the process (Figure 5-10).
Figure 5. Installing Hibernate synchronizer
Figure 6. Plug-in License Agreement
See the tradeoffs section below, which contains some discussion about license agreements. Before you decide to use Hibernate synchronizer in your own project, you may want to read it carefully. I think that's a good thing to do, but it's confusing that it's based on the GPL and it's not actually open source.
Figure 7. Choose where to install the plugin and use the default to
Figure 8. Standard warnings issued for unsigned plug-ins
Figure 9. Installing
Figure 10. Installation Complete
Now that the plug-in is installed, you need to exit and rerun eclipse for it to take effect. The dialog box appears to imply that eclipse will automatically restart, but in my experience, clicking Yes only exits the environment and must be restarted manually. This may be a limitation of the implementation of the Mac OS X for Eclipse 2.1, and Eclipse 3 will be the first to commit to providing Best-in-class support for OS X. Anyway, this is a small problem. If you need to restart Eclipse, restart now, because you should start configuring the plugin!
Configuration
After eclipse restarts, you can close the install/update perspective. Open a Java project that uses Hibernate. If you have read the examples in Developer 's Notebook book, there are several catalogs to choose from. I will use the example in chapter 3rd because this chapter is a kind of chapter that can be read online . You can also download the source code for all the examples from the site of the book.
If you are ready to create a new Eclipse project to use one of the sample source code catalogs, simply select File-> new-> project. Choose to create a Java project, and then click Next to name it (I am using "Hibernate Ch3", as shown in Figure 11), and deselect the Use default checkbox so that you can tell eclipse the location of the existing project directory, and then click the Browse button , locate its location on the drive. You can now click Finish to create the project, but I generally prefer to click Next and then check Eclipse's selections again. (Of course, if anything goes wrong, you can always go back and modify the project properties, but I find that it's a hassle to face a lot of bugs and warnings right away if there's a missing library.) )
Figure 11. Create a new project that uses hibernate
My warning here is superfluous. Eclipse is aware of the architecture and usage of the directory, and also identifies all the Third-party libraries I have downloaded and installed to allow the Hibernate and HSQLDB database engines to run. This intelligent adaptability is one of the most important features of Eclipse. Figure 12 shows that our new project is open and ready for experimentation. It also shows that eclipse does not like to shrink windows to fit the appropriate screenshot. From now on, I can only capture part of the window.
Figure 12. The example project in chapter 3rd
The next step is to create a hibernate configuration file that hibernate synchronizer can use. A hibernate.properties file already exists in the src directory, which illustrates the configuration of the example in the book, but hibernate Synchronizer can only use the Hibernate xml-based configuration method. So, we need to copy the contents of the Hibernate.properties file into a new Hibernate.cfg.xml file. On the good side, this allows us to see a feature of Hibernate Synchronizer, the Profile Wizard. Select File-> New-> Other, click the newly available Hibernate category, select Hibernate Configuration File, and then click Next.
Figure 13. Start Hibernate Configuration File Wizard
When the wizard starts, the directory that it provides to place the file depends on the file that is currently selected in Eclipse. For consistency, be sure to place it with the properties version in the top-level src directory. Fill in the rest of the information required by the wizard, matching the configuration's properties version, as shown in Figure 14. Note that unlike the execution of the Ant control Hibernate (which is the method used in Developer's Notebook book), when Hibernate is invoked, we cannot control the current working directory. So you need to use a fully qualified path to the database file in the URL. The value I use is (a bit ugly): Jdbc:hsqldb:/users/jim/documents/work/oreilly/hibernate/examples/ch03/data/music. (If anyone can tell me how to get Eclipse or hibernate synchironizer to use a specific working directory for a project, I'm definitely interested.) I am still a novice in eclipse, so it would be a surprise if I knew it was possible, but I didn't know how to do it. )
Figure 14. Fill in the details of the configuration file
It's a bit odd to fill out the driver class: You need to click the Browse button and start typing the driver's class name. If you enter "JDBCD", the window will give you only two choices, and it is easy to find the right choice, as shown in Figure 15.
Figure 15. Specifying the HSQLDB driver class
After setting the values that apply to your own installation, as shown in Figure 14, you can click Finish to create the configuration file. Hibernate Synchronizer is now ready for use. It opens the created file, so you can see the structure and details of an hibernate XML configuration file.
Figure 16. Generated configuration file
A quick way to test whether the configuration is effective is to use a different wizard interface. Select File-> New-> Other, click the newly available Hibernate category, select Hibernate Mapping File, and then click Next. When the wizard appears, it should populate all the settings you just entered, and you can click the Refresh button to determine that it communicates with the database, and it also shows that a track table was found. The first time you do this, for some reason, you may have to confirm the location of the. jar file that contains the HSQLDB driver, but this happens only once. Anyway, after confirming everything is OK, click Cancel instead of actually creating the mapping because we want to use an existing mapped file that was created manually.
Generate code
This is probably the part you've been looking forward to. What can we do in particular? Immediately there is a new context menu item that can be used to hibernate the mapped document.
If you right-click (or control) any item, you will see a number of Hibernate-related options (Figure 17), which includes a synchronization option. This is a way to manually let hibernate synchronizer generate data access objects that are related to mapping documents.
Figure 17. Sync Options for mapping documents
The Add Mapping reference option is also useful: it adds an entry in the main hibernate configuration file that informs information about the mapping document, so no content needs to be added to the source code to require the mapping to be configured. Now let's take a look at the results of choosing synchronize files.
Things are starting to get interesting here. There are two new child packages, one for hibernate synchronizer "base" data access objects that can be overwritten at any time, and the other for the business object that generates subclasses for these DAO, it will not be overridden, This gives us an opportunity to add business logic to the data class (as shown in Figure 18).
Figure 18. A synchronized data Access object that shows the editable subclasses
This generated analogy uses a lot more classes generated by the regular Hibernate code generation tool, which has some advantages as well as some potential drawbacks that we'll discuss in a later trade-off . Also note that you can select which classes to build in the project's property configuration and build their package structure. I should have shown it, but the current plugin version has a bugthat prevents access to this configuration interface on Mac OS X. The patch has been developed, but has not yet been released.
Based on the example on the Hibernate Synchronizer page and the following class, I tried to insert some data into the music database using these new data Access objects. This is very similar to the version of the standard Hibernate code generator (39-40 pages in Hibernate:a Developer's notebook book), even simpler because hibernate Synchronizer generated classes Create and submit a new transaction for each database operation, so in a simple field like this, you don't need to write code to set up a transaction. (Of course, there are a number of ways to make a set of operations run as a single transaction.) Below is the new version of the code:
Package Com.oreilly.hh;import Java.sql.time;import Java.util.date;import net.sf.hibernate.HibernateException; Import Com.oreilly.hh.dao.trackdao;import com.oreilly.hh.dao._rootdao;/** * Try creating some data using the Hibernate Sy Nchronizer approach. */public class CreateTest2 {public static void main (string[] args) throws Hibernateexception {//Load the Conf Iguration file _rootdao.initialize (); Create some sample data Trackdao DAO = new Trackdao (); Track Track = new Track ("Russian Trance", "Vol2/album610/track02.mp3", time.valueof ("00:03:30"), New Date (), (s Hort) 0); Dao.save (track); Track = new track ("Video Killed the Radio Star", "Vol2/album611/track12.mp3", time.valueof ("00:03:49"), New Dat E (), (short) 0); Dao.save (track); We don ' t even need a track variable, of Course:dao.save (new track ("Gravity's Angel", "/vol2/album175/track03.mp 3 ",Time.valueof ("00:06:06"), New Date (), (short) 0); }}
When I write this code, I can use eclipse as a very pleasant thing to do. I've forgotten how much I wish I could use the Smart Code completion feature when I write examples for books, and JDT can help in other ways as well.
To run this simple program in eclipse, we need to set up a new run configuration. Select Run-> run ... to take Createtest2.java as the current active editor file. Click New,eclipse to know that we want to run this class in the current project because we use the main () method to create it. The default name that it specifies is CreateTest2. The interface should be as shown in Figure 19. Click Run to try to create some data.
Figure 19. Ready to run our creation test in eclipse
If you do follow these steps, you will find that the first attempt at execution will fail: Hibernate complained that the configuration file does not contain a mapping reference and requires at least one. Ah ha! So this is why the yellow underline warning appears at the bottom of the Xmlbuddy. We can easily solve this problem by right-clicking on the Track.hbm.xml mapping document in the Package Explorer view and then selecting Add Mapping in the new Hibernate Synchronizer submenu Reference. This is the right approach for Xmlbuddy to keep the run going. Unfortunately, the run did not continue for long. The next error is that the JTA usertransaction initial context cannot be found in Jndi. Obviously, I'm not the only one who encounters this kind of problem, and the discussion in a forum topic is in full swing, but no one has found a solution.
Knowing that I don't need to use JTA, I want to know why hibernate try to find JTA. I opened the Hibernate configuration file ( image) and looked for anything suspicious in hibernate Synchronizer. There are certainly a few lines that are most suspect:
<property name= "Hibernate.transaction.factory_class" > Net.sf.hibernate.transaction.JTATransactionFactory </property> <property name= "JTA. UserTransaction "> java:comp/usertransaction
I tried to comment out the above and run it again, and this third run was successful. My data appears in the database because there are no errors in the run. Wow! Running a trusted Antdb goal (illustrated in chapter 1th of theDeveloper's Notebook book) will see all the data (indeed very simple), as shown in Figure 20. If you want to do this, be sure to create the database schema from a antschema, or empty any test data from the previous experiment.
Figure 20. Data created by the test program
Note that you can run your ant target in Eclipse by right-clicking (or controlling) the Build.xml file in Package Explorer, selecting Run an, and then using the Eclipse dialog box to select the target. Cool, huh?
Figure 21. Running Ant in Eclipse
Retrieving data using a query is fairly straightforward, although this time the code is close to the code used by normal data access classes that are generated by using Hibernate. Even though Hibernate Synchronizer generates a large number of helper methods for handling the specified query, I don't think any of them are particularly useful because they all insist on running the query and returning a list of results, rather than providing a query object that can be used directly. This makes it impossible for you to use query's convenient type-safe parameter setting method. Because of this, I decided to make sure that the Rootdao object provided me with a hibernate session to use the old-fashioned method. I think I can edit any of the templates used by Hibernate synchronizer to generate any method I want, and if I want to use it to develop a project, I'm pretty sure I will.
In fact, consider this further, because when you get an active session, you can only handle the method provided by Query,dao has achieved the best results. If you want to work with queries as I do in this example, you must always manage your session yourself. You can embed session management into the business logic provided by your own half DAO, which can take advantage of both. This is another reason why the split-classification model provided by Hibernate Synchronizer is so useful. I will delve into this in depth below.
Anyway, here's the first code I've come up with, basically equivalent to the code given on page 48-49 of the book:
Package Com.oreilly.hh;import Java.sql.time;import Java.util.listiterator;import Net.sf.hibernate.hibernateexception;import Net.sf.hibernate.query;import Net.sf.hibernate.session;import Com.oreilly.hh.dao.trackdao;import com.oreilly.hh.dao._rootdao;/** * Use Hibernate synchronizer ' s DAOs to run a query */p Ublic class QueryTest3 {public static void main (string[] args) throws Hibernateexception {//Load the Configur ation file and get a session _rootdao.initialize (); Session session = _rootdao.createsession (); try {//Print the tracks that'll fit in five minutes query query = session.getnamedquery ( Trackdao.query_com_oreilly_hh_tracks_no_longer_than); Query.settime ("Length", Time.valueof ("00:05:00")); for (Listiterator iter = Query.list (). Listiterator (); Iter.hasnext (); ) {Track ATrack = (Track) iter.next (); System.out.println ("Track: \") + ATrack.GetTitle () + "\", "+ atrack.getplaytime ()); finally {//No matter what, close to session session.close (); } }}
An excellent feature provided by Trackdao is a static constant, through which we can request the specified query to eliminate any possibility of a run-time error caused by a string input error. I like that! Setting up and executing the run configuration for this test class will generate the expected output, as shown in Figure 22.
Figure 22. Query results in the Eclipse console view
As I mentioned earlier, after running this class, I realized that with the help of the model provided by Hibernate Synchronizer, it could be implemented in a better way. Because the specified query is an attribute of the mapping file associated with the data Access object, if we put the query into the Trackdao object (which is where it really belongs), the object should look like this:
Package Com.oreilly.hh.dao;import Java.sql.time;import Java.util.list;import net.sf.hibernate.HibernateException; Import Net.sf.hibernate.query;import net.sf.hibernate.session;import com.oreilly.hh.base.basetrackdao;/** * This Class has been automatically generated by Hibernate Synchronizer. * For more information or documentation, visit the Hibernate Synchronizer page * at Http://www.binamics.com/hibernatesync or contact Joe Hudson at joe@binamics.com. * * This is the object class "relates to" TRACK table. * Any customizations belong. */public class Trackdao extends Basetrackdao {//Return the tracks this fit within a particular length of time publ IC Static List Gettracksnolongerthan (Time time) throws Hibernateexception {Sessions session = _ROOTDAO.CR Eatesession (); try {//Print the tracks that'll fit in five minutes query query = session.getnamedquery ( Query_com_oreilly_hh_tracks_no_longer_than); Query.settime ("Length", time); return Query.list (); finally {//No matter what, close to session session.close (); } }}
This is better and clearer, and further simplifies the main () method in QueryTest3:
public static void Main (string[] args) throws Hibernateexception { //Load The configuration file and get a Session
_rootdao.initialize (); Print the tracks that fit in five minutes List tracks = Trackdao.gettracksnolongerthan (Time.valueof ("00:05:00")); C5/>for (Listiterator iter = Tracks.listiterator (); Iter.hasnext (); ) { Track atrack = (Track) iter.next (); System.out.println ("Track: \" "+ atrack.gettitle () + " \ "," + atrack.getplaytime ()); }
Obviously, this is a way to handle the specified query when using Hibernate synchronizer. A quick test will make sure that it generates the same output, and that its code is much better.
Do you want to use Hibernate synchronizer to generate its own data Access object type Let's put it down, we have one last important feature to explore.
Edit Mappings
One of the main attractions of Hibernate Synchronizer is the specialized editor that it provides for mapping documents. You can configure this editor to automatically regenerate related data objects as long as you save the file, but this is just an icing on the cake; you might want to use this editor even if you don't intend to use the plug-in's code generator. It provides you with intelligent completion of the mapping document elements, as well as a graphical outline view that can manipulate these elements in this view.
But if you start with the download source code from Developer's Notebook book, there's at least one trick to get the editor to work. In the downloaded file, the mapping document has an extension of ". Hbm.xml" and only files that end with ". HBM" can invoke the editor. Theoretically, you can configure the extension mappings in eclipse so that files with both extensions can use the plug-in's mapping document editor, but I can't get them into effect, and I noticed that someone in the support forum faces the same problem as me. So, at least for now, the best thing to do is to rename the file. (If you insist on using ant based standard code generation, be sure to update the CodeGen target in Build.xml to use the new extension.) )
After I rename Track.hbm.xml to TRACK.HBM, its icon in Package Explorer is updated to the Hibernate logo, and the default editor becomes the editor for the plugin, as shown in Figure 23. For some reason, other hibernate synchronizer options (shown in Figure 17) are available for either of these extensions, but the editor is available only for shorter versions.
Figure 23. Hibernate The context menu for the mapped document (the extension ". hbm")
The editor provides context-sensitive AutoComplete support for all elements that are added to the mapping document. Figure 24 shows some examples, but screenshots do not really capture the depth and validity of the feature. I strongly recommend that you install the plugin and use it. You'll soon see how useful it is in dealing with mapping documents.
Figure 24 and 25. Completing accessibility in the Mapping document editor
As shown in Figure 26, outline view provides a graphical view of the class hierarchy, the mapped elements, the specified query, and the various elements in the mapping document, as well as a menu of wizards that help you create new properties.
Figures 26 and 27. Outline view of the mapping editor and the Add Property Wizard
The context menu in the editor also provides a format Source code option that you can use to organize and reconstruct the document. There are a lot of smart and useful features in this editor, and it's interesting to see how they develop. The only thing that I'm dissatisfied with is (not a big problem), when the XML attribute is finished, the way the editor uses it to help manage quotes is completely different from the way JDT is used in Java code. Switching back and forth between them will confuse the person. (You need some time to adapt to the way JDT works, but once you start trusting it, it becomes magical.) )
Generate Database Schema
Although my first impression is that everything is from a mapped document, Hibernate synchronizer currently does not support creating or updating database schemas from mapped documents. The support forum has already made relevant requests, so if you see these features in the future, I would not be surprised because it is not difficult to provide such support. For now, if you want to develop a database from a mapped document, you must use a method such as the Ant Drive in the hibernate:a Developer ' s notebook book. In addition, the Hibernator plug-in described below supports schema updates in eclipse. I might want to look at whether both of these plug-ins can be installed at the same time.
I hope this article will give you a clear idea of the functionality provided by the plug-in. Anyway, I don't have all the features covered, so if you're interested, you can go and download it and explore for yourself.
Weigh
There is no doubt that you can use Hibernate synchronizer to do some smart work. Do you want to use it in my own Hibernate project? There are advantages and disadvantages to doing this, and it is likely that I will not make a decision until we actually adopt hibernate to replace the lightweight O/R tool we are using. This was a significant change, and we postponed this change to the time of architectural change for other reasons. Here are some of the factors that play an important role in my decision.
As we mentioned in the installation section, there is a problem with licensing. There are discussions in this area in the plugin forum. The current license is based on custom modifications to the GNU GPL, which removes all source code sharing terms, but attempts to preserve other aspects of "copyleft" protection. There are still some questions about the legality of this, and the author is seeking another solution. Clearly, the goal is to protect the plug-in, not to prevent any other project from using the plug-in to generate the code, but it is necessary to read the current license carefully to see if its purpose has been met, or whether you are still at great risk.
The same discussion showed that the author originally published Plug-ins In the form of open source , but withdrew the decision temporarily because he felt it was not perfect enough to be used as a good example. Then he went through some very unpleasant emails with some reckless people, which made him reluctant to share the source code again. Of course, he has the right to decide whether to share the source code with us. The plugin is a big gift for the world, and the authors don't owe us anything. But I want him to have enough positive communication with other users so that he can make the same idea of sharing the source code. I really think it's a valuable thing to be able to see the source code of the tool I use, not only because it's a good learning opportunity, but also because it means I can fix some minor problems immediately if I need to. The author has always been enthusiastic and responsive to solving user problems, but one cannot maintain a community because we are busy, exhausted and distracted.
Hibernate Synchronizer uses its own templates and mechanisms to generate data access classes, which has both advantages and disadvantages. The advantage is that you can get more functionality than the Hibernate standard Code generation tool. It is also a good feature to use an auto-generated subclass of a data object and embed the business logic in that data object without worrying that the business logic will be overwritten when the access code is regenerated. The Plug-ins generate classes that make many simple scenarios simpler and provide other benefits.
On the other hand, it also means that when the Hibernate platform adds some new features or changes, the code generated by Hibernate Synchronizer lags behind Hibernate. The plug-in code also has bugs in support of patterns that are infrequently used by hibernate: Its user base is small and one can keep it updated. You can find evidence of this phenomenon in the discussion forum.
As with many things, it is up to you to decide whether the potential benefits outweigh the risks. Even if you don't use code generators, you'll find the mapping editor useful. If you only want to use the editor's auto completion and accessibility features, you can turn off the automatic sync option.
If you have used the plugin and found it useful, I recommend that you contact its author to express your appreciation and consider donating some money to help support its future development.
Other plugins
So far, I've also found two other plug-ins that also provide hibernate support in Eclipse. (If you know there are other plug-ins, or you will encounter such plug-ins in the future, I would like to know them.) Perhaps in the future I will also write articles about these plug-ins.
Hiberclipse
The Hiberclipse plugin also looks like a very useful tool. It seems to work with database-driven workflows, in which there is already a database schema, and you want to build a hibernate mapping file and Java classes to use that pattern. This is a very common scenario, and if you find yourself facing such a challenge, I strongly recommend that you use this plugin. It provides a very cool feature: Provide a graphical "relational view" of the databases used in eclipse. (I should point out that Hibernate synchronizer will help if you want to start with an existing database schema.) Its new Mapping File Wizard can connect to your database and build a mapping file based on what you find. )
Figure 28. Mapping Wizard for Hibernate Synchronizer
Hibernator
Finally, Hibernator seems to be inclined to another direction, that is, to generate a simple Hibernate mapping document from Java code, and then let you build (or update) the database schema from the mapped document. It also provides the ability to run database queries in eclipse. In these 3 plug-ins, the development phase seems to be the earliest, but it is worth paying attention to, especially because its developers are members of the Hibernate development team.