Is there a way to recreate the database dynamically at Run-Time in EclipseLink?
Right now I have it that if the database does not exist, it creates the database at compilation time :
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="DefaultUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
<property name="eclipselink.logging.level" value="INFO" />
<property name="eclipselink.logging.level.sql" value="INFO" />
<property name="javax.persistence.schema-generation.database.action"
value="create" />
</properties>
</persistence-unit>
</persistence>
However, I want to be able to Drop, and Recreate the database while the application is running. I.E when a user passes in some special flag, I want to call something that will drop the current database, and regenerate it.
I found that you can do that in Hibernate using the SchemaExport class
You can add <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> into persistence.xml.
It will delete all table and create it again. Be careful, all your earlier data will be lost.
absolutely. Properties can be added dynamically at runtime, so you can add the "eclipselink.ddl-generation" with value "drop-and-create-tables" when you create the EntityManagerFactory for the first time to have it drop and create the database. Of course, this isn't much use to a running app where you want to change things on the fly.
To get around this, EclipseLInk has a few tricks that allow dynamic changes and reloading of the persistence unit. Try
Map properties = new HashMap();
properties.put("eclipselink.ddl-generation", "drop-and-create-tables");
properties.put("eclipselink.ddl-generation.output-mode", "database");
//this causes DDL generation to occur on refreshMetadata rather than wait until an em is obtained
properties.put("eclipselink.deploy-on-startup", "true");
JpaHelper.getEntityManagerFactory(em).refreshMetadata(properties);
The org.eclipse.persistence.jpa.JPAHelper class is just used to unwrap the Factory to get a JpaEntityManagerFactory instance to make the non-JPA refreshMetadata call. Any number of properties or settings can be changed, and any new EntityManagers obtained after the refresh call will reflect those changes.
Related
I have Vaadin project with JPA 2.1 + EclipseLink + MySQL.
In eclipse in project settings I set connection to base and drivers correctly. Without problem I "generate Entities from Tables", but persistence.xml haven't info about driver, connection, login, pass to DB.
My auto generate persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="RadiologicalWarehouse">
<class>pl.intibs.rw.entitites.Message</class>
<class>pl.intibs.rw.entitites.Part</class>
<class>pl.intibs.rw.entitites.Role</class>
<class>pl.intibs.rw.entitites.Sample</class>
<class>pl.intibs.rw.entitites.SampleHistory</class>
<class>pl.intibs.rw.entitites.User</class>
</persistence-unit>
</persistence>
If I run my application with simple query, I get of course exception:
javax.servlet.ServletException: com.vaadin.server.ServiceException: javax.persistence.PersistenceException: Exception [EclipseLink-4021] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Unable to acquire a connection from driver [null], user [null] and URL [null]. Verify that you have set the expected driver class and URL. Check your login, persistence.xml or sessions.xml resource. The jdbc.driver property should be set to a class that is compatible with your database platform
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:239)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
If JPA has defined the connection in the project, why does not generate this persistence automatically?
Screenshot settings JPA: http://i.imgur.com/T2oEdHA.png
Based on what I understand you have set parameters for the Jpa plugin to eclipse and this is much different to set the parameters to persistence provider. Firstly you have to decide what persitent provide use and specify it in the persistence.xml together with the others paramenters.
This is an example of persistence.xml with eclipseLink:
<persistence>
<persistence-unit name="myUnit">
<provider>yourProvider</provider>
<class>it.myCompany.domain.MyFirstClass</class>
<class>it.myCompany.domain.MySecondClassClass</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="${driverClass}" />
<property name="javax.persistence.jdbc.url" value="${connectionURL}" />
<property name="javax.persistence.jdbc.user" value="${username}" />
<property name="javax.persistence.jdbc.password" value="${password}" />
<property name="eclipselink.logging.level" value="info"/>
</properties>
<shared-cache-mode>NONE</shared-cache-mode>
</persistence-unit>
</persistence>
On a Windows 8 64bit machine, in Eclipse Luna, I use JPA (EclipseLink 2.5.x) and Apache Derby as JDBC connection.
My persistence.xml so far:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="ReportWriter" transaction-type="RESOURCE_LOCAL">
<class>com.example.Clazz</class>
<class>com.example.CommentBank</class>
<class>com.example.CommentCategory</class>
<class>com.example.CourseWork</class>
<class>com.example.GradeModel</class>
<class>com.example.Pupil</class>
<class>com.example.PupilCoursework</class>
<class>com.example.Report</class>
<class>com.example.Year</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:D:\rwdb.db"/>
<property name="javax.persistence.jdbc.user" value="rwdbuser"/>
<property name="javax.persistence.jdbc.password" value="rwdbpassword"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="eclipselink.jdbc.exclusive-connection.is-lazy" value="true"/>
</properties>
</persistence-unit>
</persistence>
Using the wizard, I created a new database connection in Eclipse which works pretty well.
When I want to do JPA Tools => Generate Tables From Entities, eclipse starts creating tables... and continues forever. There's no exception, no other message, it just blocks on this operation.
I cannot even cancel it. If I try to do so, it just adds "Cancel requested" to the item and keeps going. Closing eclipse isn't possible either, as it's awaiting the finish of its current operations.
.metadata\.log doesn't contain any new information about this.
Oh and I chose "sql-script" as output, just in case.
Any ideas?
The classes that should be generated already have to be listed in persistence.xml.
Once I did this, it worked.
The reason it takes forever is that the primary process is single-threaded and probably developed by someone using legacy style coding. Even if you have 8 CPUs, the process can only use a single thread and a limited amount of memory.
I'm using JBoss 7.1 AS in my application , JPA, Hibernate and MySql DB, I configured everything well and my program is fetching data from db normal. The problem is when I try to insert some data . I found out is the normal that JTA EntityManager cannot use get Transaction , so my question is how Can i insert some data to my db ? Have no idea how Spring works so don't point me to that please, unless it's simple.
my persistance looks like that now:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="EngineProject" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MySqlDS</jta-data-source>
<class>org.itdevelopment.DAO.User</class>
<properties>
<property name="hibernate.show.sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
and my what im trying to do is simple insert some data in the ManagedBean, User class , a a method:
em.getTransaction().begin();
User employee = new User();
employee.setId(23);
employee.setCompany("Coca cola");;
employee.setLogin("James");
em.persist(employee);
em.getTransaction().commit();
as I said it returns:
A JTA EntityManager cannot use getTransaction()
So how Can I insert something ?
Thank you.
M
If you want to use Spring framework than you need to configure Spring container properly. Pleae provide spring configuration and you DAO Class content here.
Here is a link how to do this properly
http://docs.spring.io/spring/docs/3.0.x/reference/orm.html#orm-hibernate
In common case you just need
1.Configure spring and hibernate properly
2.Mark DAO methods as #Transactional with required modifier
Also take a look to Spring Data project that has out of the box solution for Hibernate
http://projects.spring.io/spring-data/
I am trying to create an application bootstrap that will drop all the tables in the application if they exist and then intialise them with fresh data.
I have created a Spring Context that loads the datasource context - however I dont know how to override the initialisation of the datasource such that the behaviour can be customised depending on how the datasource is loaded. So.. using Hibernate as my JPA implementation..
If the datasource is loaded from the application - then I would like the schemas to update:
<persistence-unit name="myDB" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
If the datasource is loaded from the bootstrap - then I need to overload this behaviour somehow so that the database is always created from scratch before fresh data is loaded:
<persistence-unit name="myDB" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
The approach I have been taking doesn't work as I would load the datasource using the 'update' setting and then drop the tables if they exist before attempting to load new data. However - the tables no longer exist for writing data !
Thanks in advance
Simon
You can pass JPA properties from Spring configuration instead of persistance.xml and use placeholder that can be configured by PlaceholderConfigurer (possibly system-properties="OVERRIDE"), or Spring profiles (since 3.1) or using Maven filtering:
<util:map id="jpaPropertyMap" key-type="java.lang.String" value-type="java.lang.Object">
<entry key="hibernate.hbm2ddl.auto" value="${database.ddl.mode}" />
</util:map>
<bean id="managementEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource"
p:jpaPropertyMap-ref="jpaPropertyMap" />
While i does manage to connect to my database through the "Services" netbeans tab, my application persistent unit seems to not be working... It just seems to go in an endless "Wait some more, maybe we'll connect you later..." cycle.
Question 1: Why isn't it working?
Question 2 (if no reasons for 1): How can i produce a small work-around?
Here is my persistent unit statement:
entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory(resourceMap.getString("entityManager.persistenceUnit")).createEntityManager();
The resourceMap.getString("entityManager.persistenceUnit")just allow me to access the property field which define my persistence unit.
Here is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="analyses_2PU" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
<class>analysesmanager.Produits</class>
<class>analysesmanager.Lots</class>
<class>analysesmanager.SpecProduits</class>
<class>analysesmanager.Parametres</class>
<class>analysesmanager.Clients</class>
<class>analysesmanager.Resultats</class>
<class>analysesmanager.Analyses</class>
<properties>
<property name="toplink.jdbc.user" value="XXXXX"/>
<property name="toplink.jdbc.password" value="XXX"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://172.17.22.15:3306/soliance_analyses"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>
While this doesn't work with my distant mysql server, it works on my local server using a local copy of the database...
The only difference is between those 2 lines...
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/soliance_analyses"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://172.17.22.15:3306/soliance_analyses"/>
By the way, running my local version, directly on the remote server does work... It seems to be an issue with either the network (which would not be solvable), either the persistence.xml used for remote connection.
Small work-around:
I have put my project local version on the remote server, and i now run it locally on the remote server, through a .bat .
Here is the ROFLMAO_it_works.bat
net use X: \\remote_server_ip\project_jar_path
X:
java -jar X:\project.jar
It works. Not the way i wanted at the very beginning, but it works.