Settng the schema of a Hibernate entity extra to the default schema configuration - spring

I have a Hibernate / Spring 4 application, where the default schema of the entity classes is already configured, e.g. they end up mapped as testschema.table or prodschema.table.
However there is another entity class which needs its own configurable schema, e.g. only this entity must be mapped to testschema2.anothertable or prodschema2.anothertable.
Nice would be something like this:
#Entity
#Table(name="anothertable", schema = "${db.AntherEntitySchema}")
public class AnotherEntity {
// ..
}
where the schema gets injected from the properties file, but such a feature seems only to work with the #Value annotation.
Any idea how to proceed?

We solved it by this applicationContextPersistence.ctx.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceXmlLocation"
value="classpath:META-INF/persistence-${env}.xml" />
<!-- .. -->
</bean>
where Spring can substitute the ${} expression from a property file.
We then have a persistence-dev.xml etc which features a specific orm-dev.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence
version="2.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_2_0.xsd">
<persistence-unit name="fooUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<mapping-file>META-INF/orm-dev.xml</mapping-file>
</persistence-unit>
<!-- .. -->
</persistence>
The orm-dev.xml is now responsible for the entity mapping:
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
version="1.0">
<description> XML Mapping file</description>
<package>foo.server.model</package>
<entity class="AnotherEntity">
<table schema="testschema2" name="anothertable" />
<attributes>
<!-- .. -->
</attributes>
</entity>
</entity-mappings>
Finally we removed the mapping annotations from the AnotherEntity POJO, as this one is now mapped via the orm-dev.xml file. The other enitity classes kept their annotations.
Note: We use the Spring Tool Suite flavour of Eclipse. This IDE expects a persistence.xml, so to get rid of an error message we kept a minimal persistence.xml to not have to remember the IDE option which deactivates the validator.

Related

Quarkus not discovering #Entity entities for persistence.xml based configuration

I'm running into an issue where I can't get Quarkus to work with persistence.xml.
My entities are not discovered so I always get "Not an entity" errors when querying.
(Caused by: java.lang.IllegalArgumentException: Not an entity: ...)
Using Quarkus 1.13.5.Final
This might be related to Quarkus Panache Not Working with persistence.xml after 1.8
I'm migrating an existing app, I only have a single project that contains all the entities. I only use a single persistence unit.
My persistence.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="registry-pu" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.jdbc.time_zone" value="UTC"/>
</properties>
</persistence-unit>
</persistence>
I'm only specifying these additional env variables:
QUARKUS_DATASOURCE_USERNAME=
QUARKUS_DATASOURCE_PASSWORD=
QUARKUS_DATASOURCE_JDBC_URL=
I'm also only relying on this persistence.xml because the app being migrated needs the enable_lazy_load_no_trans prop to work
Any help would be appreciated
Found I had to add <class>EntityClass</class> entries to the <persistence-unit> tag for each of my entities to have them included. Otherwise you may be able to try <exclude-unlisted-classes>false</exclude-unlisted-classes>

Tomcat 7 - Spring 3.2.1 - OpenJPA No persistent class is specified in eager initialization mode

I'm trying to get a simple web app called Debugger running under Tomcat 7 using Spring 3.2.1 and OpenJPA. I use Eclipse as the IDE and run Tomcat external to the IDE. I'm getting a error when the WAR is being deployed. This is the error message:
org.apache.openjpa.persistence.ArgumentException: No persistent class is specified in eager initialization mode.
Here is the persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
-->
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<persistence-unit name="applicationDB" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<properties>
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
<property name="openjpa.InitializeEagerly" value="true"/>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
</properties>
</persistence-unit>
</persistence>
Is the error caused by not having any classes specified in this file? I'm just trying to get a base application configuration setup so I'm not yet ready to place any classes in the persistence file. Maybe you have to have at least one?
Either list your persistent classes, or remove the openjpa.InitializeEagerly property.

Spring config custom namespace

I have a standalone spring application with an embedded Apache FTP server. The config looks like this -
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:afs="http://mina.apache.org/ftpserver/spring/v1"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd">
<context:property-placeholder location="classpath:config.properties" system-properties-mode="OVERRIDE"/>
<afs:server id="server" anon-enabled="false">
<afs:listeners>
<afs:nio-listener name="default" port="2222"
idle-timeout="60" />
</afs:listeners>
<!-- other AFS config -->
</afs:server>
</beans>
I would like to load the port property of nio-listener from a properties files, but
<afs:nio-listener name="default" port="${ftp.port}"
idle-timeout="60" />
doesn't work, since port is defined in the xsd as xs:int. I'd like to know if there is any workaround (using SpEL?) that will allow me to use the AFS namespace and load the port property from a file or from system properties.
You could try with PropertyOverrideConfigurer.
The problem is that you need to know the bean name that the <afs:server> tag define (may be 'server') and the property type that <afs:listeners> define (may be a managed list of bean definitions).
Look at STS bean explorer to find correct answers and try whith something like
<context:property-override location="classpath:config.properties" />
server.listeners[0].port=2222
Other option is disable schema validation setting validating to false before refresh in the xml application context.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml"}, false);
context.setValidating(false);
context.refresh();
After exploring a few options, I've decided that the easiest way is to step outside the afs namespace for the just the listener configuration. Final config looks like this -
<bean id="listenerFactory" class="org.apache.ftpserver.listener.ListenerFactory">
<property name="port" value="${ftp.port}" />
<property name="dataConnectionConfiguration">
<bean factory-bean="dataConnectionConfigurationFactory"
factory-method="createDataConnectionConfiguration" />
</property>
</bean>
<bean id="dataConnectionConfigurationFactory" class="org.apache.ftpserver.DataConnectionConfigurationFactory" />
<bean id="nioListener" factory-bean="listenerFactory" factory-method="createListener" />
<afs:server id="server" anon-enabled="false">
<afs:listeners>
<afs:listener name="default">
<ref bean="nioListener"/>
</afs:listener>
</afs:listeners>
<!-- other AFS config -->
</<afs:server>

Spring JPA & Hibernate persistence_1_0.xsd not found

So i Have this problem in implementing JPA and Hibernate in Spring WS. I have configured everything correctly and according to tutorial it should work - but it is not.
Problem lies in persistance.xml, here it is how it looks:
<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/persistance_1_0.xsd"
version="1.0">
<persistence-unit name="hibernatePersistenceUnit" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.hbm2ddl.auto" value="none" />
</properties>
</persistence-unit>
</persistence>
and the exception i am getting:
Caused by: java.io.FileNotFoundException: class path resource [persistence_1_0.xsd] cannot be resolved to URL because it does not exist
at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:177)
at org.springframework.orm.jpa.PersistenceUnitReader.validateResource(PersistenceUnitReader.java:281)
at org.springframework.orm.jpa.PersistenceUnitReader.readPersistenceUnitInfos(PersistenceUnitReader.java:108)
... 57 more
I am struggling with this since a while... Do anyone have an idea what am i missing?
You need to include appropriate jar file containing the persistence_1_0.xsd.
This is explained here.
what is the use of xsi:schemaLocation?
There was a type in the url to the .xsd file. Try using: http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd . A good way to debug these types of issues is to try to hit the url in your browser, a successful request denotes a valid link.
<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_1_0.xsd"
version="1.0">
<persistence-unit name="hibernatePersistenceUnit" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.hbm2ddl.auto" value="none" />
</properties>
</persistence-unit>
</persistence>
You make sure your project name does not contain any spaces, nor should the path to the project. This creates an error in Hibernate entity manager.

Why do I get an unexpected EntityManagerFactory when using JPA within WebLogic?

I am trying to create a Spring MVC web app (Spring Framework 3.0.5). I am using IntelliJ IDEA 11.1.3 to deploy my app on a WebLogic Server (10.3.4). One of my web pages attempts to store some data in a database using JPA. My persistence.xml specifies:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="LeaveSchedulerJPA" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.engilitycorp.leavetracker.jpa.UserRole</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#localhost:1521:xe "/>
<property name="javax.persistence.jdbc.user" value="leavescheduler"/>
<property name="javax.persistence.jdbc.password" value="xxx"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
</properties>
</persistence-unit>
</persistence>
However, when I look in the debugger, my EntityManagerFactory is shown as an org.apache.openjpa.persistence.EntityManagerFactoryImpl, and when I call createEntityManager, I get an org.apache.openjpa.persistenceArgumentException that states that "A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property".
It appears to my newbie eye that the persistence.xml may not be getting processed. I've tried putting it in (project)/src/main/resources/META-INF and (project)/src/main/resources/META-INF/spring, with the same unfortunate result.
I am not committed to using Hibernate persistence; however, I do want to use something that implements JPA 2, and I am having a real hard time configuring my environment. For example, I have little idea how openjpa got involved in my app. I suppose it may be the default JPA provider for something (WebLogic?, IntelliJ IDEA?). Any help/suggestions would be much appreciated.
My web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
root-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.engilitycorp.leavetracker" />
</beans:beans>
WebLogic 10.3.4 is Java EE 5 compliant and is shipped with JPA 1.0 implementations: OpenJPA and TopLink.
According to WebLogic documentation ( http://docs.oracle.com/cd/E17904_01/web.1111/e13720/using_toplink.htm#CIHDJHHI ) it can be used also with JPA 2.0 but only after applying a patch. Simply follow the instructions (patching seems to be quite simple but I didn't test it).
Probably you can also use your own JPA 2.0 provider without patching, as user1654209 wrote in first answer. But JPA 1.0 classes supplied with WebLogic can get in the way, because they are loaded by higher level classloader and have priority over classes packaged in your WAR file. To prevent such behaviour you have two options:
pack your application's WAR within an EAR archive with META-INF/weblogic-application.xml file containing following lines (you must also include standard META-INF/application.xml file):
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://xmlns.oracle.com/weblogic/weblogic-application/1.0/weblogic-application.xsd">
<prefer-application-packages>
<package-name>javax.persistence.*</package-name>
</prefer-application-packages>
</weblogic-application>
add WEB-INF/weblogic.xml file to your WAR archive with following lines:
<?xml version='1.0' encoding='UTF-8'?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
You need to configure an entityManagerFactory bean in your context.xml. Heres is an exemple using eclipselink as the JPA provider
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
</bean>
</property>
</bean>
Just setting the provider isn't enough. You need to set the database connection data, like jdbc url, username and password. Did you set it? You also need to set the jdbc class name, as said, and the jdbc driver needs to be in your classpath.
If you are running this on a container and want to configure the datasource in weblogic, you can just refer to a jndi datasource from your hibernate cfg, but you will need to enter in the weblogic console and create a datasource and a connection pool there.
Look at hibernate docs on how to set the JNDI name in persistence.xml

Resources