New database user instance created when Spring JDBC Template use calling Procedure - spring

I have using Spring Mvc Jdbc template for calling procedures and functions.But the database connection is not close after the function call.Every time new database user instance create.Could anyone please give me the solution for solving this big problem.
#Autowired
#Qualifier("dbDataSource")
public DataSource dataSource;
public SimpleJdbcCall procReadData;
public PersonDTO readPersonData(Principal principal) throws SQLException {
List<PersonDTO> personDTOList = null;
Map<String,Object> results = null;
procReadData = new SimpleJdbcCall(dataSource).withProcedureName("GET_PAWS_PERSON_DETAILS");
procReadData.addDeclaredParameter(new SqlParameter("AV_USER_NAME", OracleTypes.VARCHAR));
procReadData.addDeclaredParameter( new SqlOutParameter( "CUR_GENERIC", OracleTypes.CURSOR,new PersonRowMapper()));
SqlParameterSource in = new MapSqlParameterSource().addValue("AV_USER_NAME", principal.getName());
results = procReadData.execute(in);
Set<String> keys = results.keySet();
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
personDTOList = (List<PersonDTO>) results.get(key);
}
return personDTOList.get(0);
}
Database Configuration:
<Resource driverClassName="oracle.jdbc.OracleDriver" maxActive="300" maxIdle="100" maxWait="5000" name="jdbc/epaws" global="jdbc/epaws"
password="polusneu" type="javax.sql.DataSource" url="jdbc:oracle:thin:#192.168.1.60:1521:coeusnew"
username="polusneu" validationQuery="select 1 from dual"/>
applicationcontext.xml configuration
<bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/epaws"/>
<property name="resourceRef" value="true"/>
</bean>

Related

Using mocked dataSource bean when testing Camel route

I have a dataSource bean defined in spring xml as follows
<bean id="apacheBasicDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" >
<property name="url" value="jdbc:oracle:thin:#(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = myservice)))" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
...
</bean>
Now I want to test a rest route which do his job by calling stored procedure within a groovy script
<get uri="/utils/foo" produces="text/xml">
<route id="utils.foo">
<setBody>
<groovy>
import groovy.sql.Sql
def sql = Sql.newInstance(camelContext.getRegistry().lookupByName('apacheBasicDataSource'))
res = request.getHeader('invalues').every { invalue ->
sql.call("{? = call my_pkg.mapToSomeValue(?)}", [Sql.VARCHAR, invalue]) {
outValue -> do some stuff..
}
}
sql.close()
new StringBuilder().append(
some stuff..
)
</groovy>
</setBody>
</route>
</get>
I have my test class as follows, so now it works
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = {"classpath:camel.xml"})
public class EdiapiApplicationNewTest {
#Autowired
private CamelContext context;
#MockBean private DataSource dataSource;
#Mock private CallableStatement callableStatement;
#Mock private Connection connection;
#Mock private ResultSet resultSet;
#Test
public void testSimple() throws Exception {
when(callableStatement.getResultSet()).thenReturn(resultSet);
when(dataSource.getConnection()).thenReturn(connection);
when(connection.prepareCall(anyString())).thenReturn(callableStatement);
context.getRegistry().bind("apacheBasicDataSource", dataSource);
TestRestTemplate restTemplate = new TestRestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:8080/utils/foo?invalues=foo,bar", String.class);
Assert.assertEquals("<value>false</value>", response.getBody());
}
}
But I want to be able to populate mocked ResultSet with some custom value to test against (at the moment it returns null)
I have tried something like
when(resultSet.next()).thenReturn(true).thenReturn(false);
when(resultSet.getString(anyInt())).thenReturn("some value");
With no success. Could someone give me a hint about it?
Thanks!
Finally I found the roots of the issue as well as a solution.
First, void call method should be mocked with doAnswer and not with thenReturn (obviously).
Second, I dealt with stored function, so there was no getResultSet method invoking on callableStatement, instead the getObject method was invoked, so this is the one should be mocked as
when(callableStatement.getObject(1)).thenAnswer(inv -> "some custom value");

Hibernate ClassCastException when retrieving a class from query.getResultList

I created a small SpringBoot App which is used together with Hibernate to work with our Oracle Databse.
But I ran into the following Problem:
Whenever I load an Object from the database with SessionFactory.createQuery() and then query.getResultList(). I do get a List of Results with the correct Class annotations (when looking at the code in debug mode). But I cannot do MyClass x = list.get(0), even though the list is a List of MyClass. I can only get an Object but cannot "cast" to the correct class.
Uidnr is a simple Class with no join tables or any other dependencies on other tables form the database. Its only BigDecimal's, String's and Timestamp's.
Here is the code and configs of everything:
POST Endpoint:
#RequestMapping(value = "/e10", method = RequestMethod.POST, produces = MediaType.APPLICATION_XML_VALUE)
#ResponseBody
public String e10() {
Database db = new Database();
List<Uidnr> bel = db.getUidnrList(new BigDecimal("1009316"));
Uidnr element = bel.get(0); //CLASSCASTEXCEPTION HERE!!!
return element.getNr();
}
Method to get the Class from Database:
public List<Uidnr> getUidnrList(BigDecimal id) {
SessionFactory factory = null;
List<Uidnr> uidnr = new ArrayList<Uidnr>();
Session session = null;
try {
factory = getSessionFactory();
session = factory.openSession();
Query<Uidnr> query = session.createQuery("from Uidnr where adrid=:sblid", Uidnr.class);
query.setParameter("sblid", id);
uidnr = query.getResultList(); //This is a List<Uidnr
} catch (HibernateException ex) {
logger.error("Error loading Sendungen.", ex);
} finally {
close(factory, session);
}
return uidnr;
}
SessionFactory:
private SessionFactory getSessionFactory() {
SessionFactory sf = null;
File optextconf = new File("conf/hibernate.cfg.xml");
Configuration c = new Configuration();
if (optextconf.exists()) {
c.configure(optextconf);
c.addResource("eu/lbase/invsvc/app/model/internal/Uidnr.hbm.xml");
sf = c.buildSessionFactory();
logger.info("Session factory loaded from external file {}.", optextconf.getAbsolutePath());
} else {
logger.error("Configuration {} not found. Can not connect to database.", optextconf.getAbsolutePath());
}
return sf;
}
Uidnr.hbm.xml file located under src/main/resources, in a package called eu.lbase.invsvc.app.model.internal:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="eu.lbase.invsvc.app.model.internal.Uidnr" table="SUID_UIDNR">
<composite-id>
<key-property name="adrid" column="UID_ADRID" />
<key-property name="staid" column="UID_STAID" />
</composite-id>
<property name="nr" column="UID_NR"/>
<property name="stnr" column="UID_STNR"/>
<property name="deflt" column="UID_DEFLT"/>
<property name="aend" column="UID_AEND"/>
<property name="usrid" column="UID_USRID"/>
<property name="stktonr" column="UID_STKTONR"/>
<property name="zoktonr" column="UID_ZOKTONR"/>
<property name="vollmacht" column="UID_VOLLMACHT"/>
</class>
</hibernate-mapping>
Exception:
java.lang.ClassCastException: eu.lbase.invsvc.app.model.internal.Uidnr cannot be cast to eu.lbase.invsvc.app.model.internal.Uidnr
at eu.lbase.invsvc.app.controller.WebController.e10(WebController.java:91) ~[main/:na]
Some Tests:
System.out.println(bel.getClass()); //class java.util.ArrayList
Object test = bel.get(0);
System.out.println(test.getClass()); //class eu.lbase.invsvc.app.model.internal.Uidnr
System.out.println(bel.get(0) instanceof eu.lbase.invsvc.app.model.internal.Uidnr); //false

Proxy database not switching

Spring framework 4.1.4
Spring batch 3.0.2
Tomcat 7
Morning,
I have successfully used a configuration based on Marten Deinum's Post
to dynamically connect (or create and connect) to dbs only known at run time.
The problem I am having is the process now intermittently fails to switch between dbs. The first always works but putting in logging code shows the first properly being created and then the second or third not firing dataSource == null section in the MdyDataSourceFactory - it appears if the process thinks it is the same db and so doesn't change but at some point it triggers and connects to a subsequent db!
Running a simple JUnit test switching between dbs works fine (code correctly fires and dbs switch and select statement returns different id results as expected).
It is being called within a Batch Job step tasklet. The process grabs a count of resultSets (summary table) and connects to the db. For each resultSet it calls the db registry and if exists - returns existing or creates a new one and returns.
My dynamic db xml is:
<bean id="mdyDSRegistry" class="com.k12knowledge.db.MdyDataSourceFactory" />
<bean id="mdyDSTargetSource" class="com.k12knowledge.db.ContextSwappableMdyTargetSource">
<constructor-arg type="java.lang.Class">
<value>javax.sql.DataSource</value>
</constructor-arg>
<property name="targetRegistry" ref="mdyDSRegistry"></property>
</bean>
<bean id="proxyMdyDataSource" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>javax.sql.DataSource</value>
</list>
</property>
<property name="targetSource">
<ref bean="mdyDSTargetSource" />
</property>
</bean>
The MdyDataSourceFactory is:
public class MdyDataSourceFactory implements TargetRegistry {
private ConcurrentMap<String, DataSource> map = new ConcurrentHashMap<String, DataSource>();
#Override
public DataSource getTarget(String context) {
IClientDs client = MdyContextHolder.getClientDs();
Assert.notNull(client, "Client was not set.");
String key = client.getUrl();
DataSource dataSource = map.get(key);
if (dataSource == null) {
System.out.println("dataSource == null - creating new");
dataSource = getDataSource(client);
dataSource = map.putIfAbsent(key, dataSource);
if (dataSource == null) {
// put success
dataSource = map.get(key);
}
}
System.out.println("client key: " + key);
return dataSource;
}
private DataSource getDataSource(IClientDs client) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(client.getDriver());
dataSource.setUrl(client.getUrl());
dataSource.setUsername(client.getUsername());
dataSource.setPassword(client.getPassword());
dataSource.setValidationQuery("/* ping */");
dataSource.setMaxActive(10);
dataSource.setMaxIdle(5);
dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(true);
dataSource.setRemoveAbandoned(true);
dataSource.setRemoveAbandonedTimeout(20);
dataSource.setTimeBetweenEvictionRunsMillis(34000);
dataSource.setMinEvictableIdleTimeMillis(55000);
try {
System.out.println("dataSource " + client.getUrl() + " closed ? " + dataSource.getConnection().isClosed());
} catch (SQLException e) {
e.printStackTrace();
}
return dataSource;
}
}
At one point I thought there was an issue with the key I used (some databases are only different in name by 1 letter). I then tried adding an UUID to the front of the key to see if that was the issue - no change.
Really puzzled as to why it is not working... Any pointers greatly appreciated.
Thank you for looking.
ContextHolder
public abstract class ContextHolder {
private static final ThreadLocal<IClientDs> holder = new ThreadLocal<IClientDs>();
public static void setClientDs(IClientDs context) {
LoggerFactory.getLogger(ContextHolder.class).debug("context set '{}'", context);
holder.set(context);
}
public static IClientDs getClientDs() {
return (IClientDs) holder.get();
}
}

Spring: import a module with specified environment

Is there anything that can achieve the equivalent of the below:
<import resource="a.xml">
<prop name="key" value="a"/>
</import>
<import resource="a.xml">
<prop name="key" value="b"/>
</import>
Such that the beans defined in resouce a would see the property key with two different values? The intention would be that this would be used to name the beans in the imports such that resource a.xml would appear:
<bean id="${key}"/>
And hence the application would have two beans named a and b now available with the same definition but as distinct instances. I know about prototype scope; it is not intended for this reason, there will be many objects created with interdepednencies that are not actually prototypes. Currently I am simply copying a.xml, creating b.xml and renaming all the beans using the equivalent of a sed command. I feel there must be a better way.
I suppose that PropertyPlaceholderConfigurers work on a per container basis, so you can't achieve this with xml imports.
Re The application would have two beans named a and b now available with the same definition but as distinct instances
I think you should consider creating additional application contexts(ClassPathXmlApplicationContext for example) manually, using your current application context as the parent application context.
So your many objects created with interdependencies sets will reside in its own container each.
However, in this case you will not be able to reference b-beans from a-container.
update you can postprocess the bean definitions(add new ones) manually by registering a BeanDefinitionRegistryPostProcessor specialized bean, but this solution also does not seem to be easy.
OK, here's my rough attempt to import xml file manually:
disclaimer: I'm very bad java io programmer actually so double check the resource related code :-)
public class CustomXmlImporter implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
private Map<String, String> properties;
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public Map<String, String> getProperties() {
return properties;
}
private void readXml(XmlBeanDefinitionReader reader) {
InputStream inputStream;
try {
inputStream = new ClassPathResource(this.classpathXmlLocation).getInputStream();
} catch (IOException e1) {
throw new AssertionError();
}
try {
Scanner sc = new Scanner(inputStream);
try {
sc.useDelimiter("\\A");
if (!sc.hasNext())
throw new AssertionError();
String entireXml = sc.next();
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${",
"}", null, false);
Properties props = new Properties();
props.putAll(this.properties);
String newXml = helper.replacePlaceholders(entireXml, props);
reader.loadBeanDefinitions(new ByteArrayResource(newXml.getBytes()));
} finally {
sc.close();
}
} finally {
try {
inputStream.close();
} catch (IOException e) {
throw new AssertionError();
}
}
}
private String classpathXmlLocation;
public void setClassPathXmlLocation(String classpathXmlLocation) {
this.classpathXmlLocation = classpathXmlLocation;
}
public String getClassPathXmlLocation() {
return this.classpathXmlLocation;
}
#Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
readXml(reader);
}
}
XML configuration:
<bean class="CustomXmlImporter">
<property name="classPathXmlLocation" value="a.xml" />
<property name="properties">
<map>
<entry key="key" value="a" />
</map>
</property>
</bean>
<bean class="CustomXmlImporter">
<property name="classPathXmlLocation" value="a.xml" />
<property name="properties">
<map>
<entry key="key" value="b" />
</map>
</property>
</bean>
this code loads the resources from classpath. I would think twice before doing something like that, anyway, you can use this as a starting point.

Using #Table with schema name in Hibernate 3.3.1ga and HSQLDB

How can I make this work in unit tests using Hibernate 3.3.1ga and HSQLDB:
#Entity
#Table(name="CATEGORY", schema="TEST")
public static class Category { ... }
The problem is that Hibernate expects the schema to exist. The second problem is that Hibernate issues the CREATE TABLE TEST.CATEGORY before any of my code runs (this happens deep inside Spring's test setup), so I can't get a connection to the DB before Hibernate and create the schema manually.
But I need the schema because I have to access different databases in the real code. What should I do?
Hibernate 3.3.1ga, HSQLDB, Spring 2.5
You could write a class that implements InitializingBean:
public class SchemaCreator implements InitializingBean {
private String schema;
private DataSource dataSource;
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public void afterPropertiesSet() throws Exception {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute("CREATE SCHEMA " + schema + " AUTHORIZATION DBA");
}
}
You then have to define a bean in your bean definition file of this class (I'm taking a shot in the dark as to what your existing bean definitions look like).
<bean id="dataSource" class="...">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" depends-on="schemaCreator" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
...
</bean>
<bean id="schemaCreator" class="SchemaCreator">
<property name="dataSource" ref="dataSource"/>
<property name="schema" value="TEST"/>
</bean>
By using the depends-on attribute of Hibernate's bean, Spring will ensure that the schemaCreator bean will be initialized first, causing the schema to exist just in time. This should also make your intentions clearer.
My current solution looks like this:
#Override
protected String[] getConfigLocations() {
createHSQLDBSchemas ();
return new String[]{
"test-spring-config.xml"
};
}
private static boolean hsqldbSchemasCreated = false;
public static void createHSQLDBSchemas ()
{
if (hsqldbSchemasCreated)
return;
try
{
log.info ("createHSQLDBSchemas");
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:test", "sa", "");
Statement stmt = c.createStatement ();
String sql;
sql = "CREATE SCHEMA xxx AUTHORIZATION DBA";
log.info (sql);
stmt.execute (sql);
stmt.close ();
c.close ();
}
catch (Exception e)
{
throw new ShouldNotHappenException (e);
}
hsqldbSchemasCreated = true;
}
but that feels like a really ugly hack. Isn't there a better solution?
Below is an example of how you can create spring config with test hslqdb
It automaticly detects all your schemas from #Table(schema =...) and creates them for you.
If it is just for testing this should work for you:
import org.reflections.Reflections; //maven artifact: 'org.reflections:reflections:0.9.9-RC1'
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
#Configuration
#ComponentScan("com.test.collection")
public class CollectionConfig {
private static final String[] ENTITY_PACKAGES = { "com.test.collection.domain.dao" };
private static final String CONFIGURATION_LOCATION = "/movie-collection-hibernate.cfg.xml";
#Bean( name = "testSessionFactory" )
#Lazy
public LocalSessionFactoryBean getTestSessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setPackagesToScan( ENTITY_PACKAGES );
Properties hibernateProperties = getHibernateHsqlTestDbProperties();
sessionFactory.setHibernateProperties( hibernateProperties );
createNonStandardSchemas( hibernateProperties );
return sessionFactory;
}
private void createNonStandardSchemas( Properties properties ) {
final String DEFAULT_SCHEMA = "";
Set<String> schemas = new HashSet<>();
Reflections reflections = new Reflections( ENTITY_PACKAGES );
Set<Class<?>> annotatedClasses =
reflections.getTypesAnnotatedWith( Table.class );
for ( Class<?> clazz : annotatedClasses ) {
Table table = clazz.getAnnotation( Table.class );
if ( !DEFAULT_SCHEMA.equals( table.schema() ) ) {
schemas.add( table.schema() );
}
}
if ( !schemas.isEmpty() ) {
DriverManagerDataSource driverManager = new DriverManagerDataSource();
driverManager.setDriverClassName( properties.getProperty( "hibernate.connection.driver_class" ) );
driverManager.setUrl( properties.getProperty( "hibernate.connection.url" ) );
driverManager.setUsername( properties.getProperty( "hibernate.connection.username" ) );
driverManager.setPassword( properties.getProperty( "hibernate.connection.password" ) );
JdbcTemplate jdbcTemplate = new JdbcTemplate( driverManager );
for ( String schemaName : schemas ) {
jdbcTemplate.execute(
String.format( "DROP SCHEMA IF EXISTS %s", schemaName)
);
jdbcTemplate.execute(
String.format( "CREATE SCHEMA %s AUTHORIZATION DBA", schemaName)
);
}
}
}
private Properties getHibernateHsqlTestDbProperties() {
Properties prop = new Properties();
prop.setProperty( "hibernate.connection.driver_class", "org.hsqldb.jdbcDriver" );
prop.setProperty( "hibernate.connection.url", "jdbc:hsqldb:mem:test" );
prop.setProperty( "hibernate.connection.username", "sa" );
prop.setProperty( "hibernate.connection.password", "test" );
prop.setProperty( "hibernate.connection.pool_size", "5" );
prop.setProperty( "hibernate.dialect", "org.hibernate.dialect.HSQLDialect" );
prop.setProperty( "hibernate.current_session_context_class", "thread" );
prop.setProperty( "hibernate.cache.provider_class", "org.hibernate.cache.internal.NoCachingRegionFactory" );
prop.setProperty( "hibernate.show_sql", "false" );
prop.setProperty( "hibernate.format_sql", "false" );
prop.setProperty( "hibernate.use_sql_comments", "false" );
prop.setProperty( "hibernate.hbm2ddl.auto", "create-drop" );
return prop;
}
}
And here is a test sample:
#ContextConfiguration( classes = CollectionConfig.class )
#DirtiesContext( classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD )
public class DaoMappingTest extends AbstractTestNGSpringContextTests {
#Autowired
private SessionFactory testSessionFactory;
#Test
public void thatMovieIsSaved() {
Movie killBill = getKillBillMovie0();
saveToDb( Arrays.asList(killBill) );
Session querySession = testSessionFactory.openSession();
List<Movie> movies = querySession.createQuery( "from Movie" ).list();
querySession.close();
assertThat( movies ).containsExactly( killBill );
}
#Test
public void that2MoviesIsSaved() {
Movie killBill = getKillBillMovie0();
Movie terminator = getTerminatorMovie1();
saveToDb( Arrays.asList( killBill, terminator ) );
Session querySession = testSessionFactory.openSession();
List<Movie> movies = querySession.createQuery( "from Movie" ).list();
querySession.close();
assertThat( movies ).containsOnly( killBill, terminator );
}
private void saveToDb( List<?> objects ) {
Session session = testSessionFactory.openSession();
session.beginTransaction();
for( Object obj : objects) {
session.save( obj );
}
session.getTransaction().commit();
session.close();
}
#AfterSuite
public void tearDown() {
testSessionFactory.close();
}
}
It looks to me like you have a reproducible bug in the Hibernate DDL creation code. You should report a bug - it's a long term solution but it's the way things are done in open source. Of course you might want to produce a patch, but I never found the Hibernate code base easy to hack.
I ran into the same problem where MS SQL Server wants the catalog and schema defined, but HSQLDB does not. My solution was to load a custom orm.xml file (via persistence.xml) specifically for MS SQL Server that sets the catalog and schema.
1.Only specify the #Table name (omit any catalog or schema info) for your entity:
#Entity
#Table(name="CATEGORY")
public static class Category { ... }
2.Specify two persistence-unit nodes in your META-INF/persistence.xml file
<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">
<!--
| For production and integration testing we use MS SQL Server, which needs
| the catalog and schema set (see orm-mssql.xml).
|-->
<persistence-unit name="com.mycompany.prod">
<mapping-file>META-INF/orm-mssql.xml</mapping-file>
</persistence-unit>
<!--
| For unit testing we use HSQLDB, which does not need the catalog or schema.
|-->
<persistence-unit name="com.mycompany.test" />
</persistence>
3.Specify the default catalog and schema in the orm-mssql.xml file:
<entity-mappings version="2.0"
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 orm_2_0.xsd">
<persistence-unit-metadata>
<!--
| Set the catalog and schema for MS SQL Server
|-->
<persistence-unit-defaults>
<schema>MYSCHEMA</schema>
<catalog>MYCATALOG</catalog>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>
4.I'm using Spring to configure JPA, so I use a property-placeholder for the value of the persistenceUnitName:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="persistenceUnitName" value="${entityManagerFactory.persistenceUnitName}" />
</bean>
For unit tests, use 'com.mycompany.test' and for integration-tests/production deployments, use 'com.mycompany.prod'.

Resources