Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Teneo/Hibernate/QuickStart
Contents
This quick start shows how EMF, Teneo and Hibernate work together to automatically creates the database schema and persist EMF objects.
The quick start tutorial uses the example project which you can download here.
This tutorial assumes some basic knowledge of EMF. If you are new to EMF then it can make sense to first try one of the core EMF tutorials which you can find here.
Initial Setup
The quick start assumes that you have a running Eclipse with EMF and Teneo installed. In addition the Teneo dependencies (incl. hsqldb and mysql drivers) should be installed. See the Download & Install page for more information.
The quick start uses hsqldb but it can easily be changed to use mysql or another database. For other databases than hsqldb and mysql you need to take make sure that the jdbc driver is in the classpath of the org.eclipse.emf.teneo.hibernate.examples project.
For mysql and other non-in-memory databases you have to create the database up-front (so not the tables inside the database but just the database itself). For the quick start the database name should be: library.
Running 'quick start'
After downloading the examples project from cvs you can directly run the quick start program. Open the project and navigate to the QuickStart.java file and right click and select 'Run As > Java Application'. You will see several things getting printed to the console (one of them is the generated Hibernate mapping).
This run takes the following steps:
- reads the EPackage model from the generated EPackage file.
- generate a hibernate mapping for the EPackage
- create the database (on hsqldb)
- create EMF objects and persist them
Walk-through
Now let's walk through the code of the quick start to understand what it does. There are two distinct phases: 1) initialization and 2) runtime. Teneo is called/used explicitly in the initialization phase. In the runtime phase you will see that you only use EMF and Hibernate.
Initialization
The code starts with setting hibernate database connection properties:
// The hibernate properties can be set by having a hibernate.properties file in the root of // the classpath. // Another approach is setting the properties in the HbDataStore. // For more information see section 3.1 of the Hibernate manual final Properties props = new Properties(); props.setProperty(Environment.DRIVER, "org.hsqldb.jdbcDriver"); props.setProperty(Environment.USER, "sa"); props.setProperty(Environment.URL, "jdbc:hsqldb:mem:library"); props.setProperty(Environment.PASS, ""); props.setProperty(Environment.DIALECT, org.hibernate.dialect.HSQLDialect.class.getName());
Teneo supports many configuration options which control the mapping and runtime behavior. The quick start shows an example on how to set one:
Note: the above configuration uses the hsqldb in-memory storage, if you use the hsqldb file storage, don't forget to add this code before closing the session:
session.createSQLQuery("SHUTDOWN").executeUpdate();
Otherwise nothing gets written to the file system.
// set a specific option // see this page http://wiki.eclipse.org/Teneo/Hibernate/Configuration_Options // for all the available options props.setProperty(PersistenceOptions.CASCADE_POLICY_ON_NON_CONTAINMENT, "REFRESH,PERSIST,MERGE");
Then a datastore is created. A datastore controls the persistence of one or more EPackages. In addition the properties defined above are set in the store.
// the name of the session factory String hbName = "Library"; // create the HbDataStore using the name final HbDataStore hbds = HbHelper.INSTANCE.createRegisterDataStore(hbName); // set the properties hbds.setDataStoreProperties(props);
As a next step the EPackages are set and the datastore is initialized:
// sets its epackages stored in this datastore hbds.setEPackages(new EPackage[] { ExtlibraryPackage.eINSTANCE }); // initialize, also creates the database tables try { hbds.initialize(); } finally { // print the generated mapping System.err.println(hbds.getMappingXML()); }
This initialization step maps the EPackages to hibernate and creates the database schema. The generated hibernate mapping is printed to the console.
As a last initializiation step the Hibernate SessionFactory is created:
SessionFactory sessionFactory = hbds.getSessionFactory();
Runtime
At runtime first a Hibernate Session is created. Then the Library is instantiated and persisted:
// Create a session and a transaction Session session = sessionFactory.openSession(); Transaction tx = session.getTransaction(); // Start a transaction, create a library and make it persistent tx.begin(); Library lib = ExtlibraryFactory.eINSTANCE.createLibrary(); lib.setName("My Library"); session.save(lib);
Then in the next steps a Book and Writer is created and the transaction is committed:
// create a writer Writer writer = ExtlibraryFactory.eINSTANCE.createWriter(); writer.setName("JRR Tolkien"); // and one of his books Book book = ExtlibraryFactory.eINSTANCE.createBook(); book.setAuthor(writer); book.setPages(305); book.setTitle("The Hobbit"); book.setCategory(BookCategory.SCIENCE_FICTION); session.save(book); // add the writer/book to the library. The writer and book are automatically // made persistent because they are added to the library which is already // made persistent lib.getWriters().add(writer); lib.getBooks().add(book); // at commit the objects will be present in the database tx.commit(); // and close of, this should actually be done in a finally block session.close();
When you now check your database you will see that tables got created and the above objects have been persisted:
Next tutorials will show how to read the information from the database.
Try some changes
You can try out mysql or another database by changing the properties in the beginning of the quick start:
props.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver"); props.setProperty(Environment.USER, "root"); props.setProperty(Environment.URL, "jdbc:mysql://127.0.0.1:3306/" + dbName); props.setProperty(Environment.PASS, "root"); props.setProperty(Environment.DIALECT, org.hibernate.dialect.MySQL5InnoDBDialect.class.getName());
Make sure that the jdbc driver is in the classpath and that the database (called library) is created before running the quick start.
As a next step you can change the ecore model and regenerate the model code and re-run the quick start. You will see the changes reflected in the database schema.