How to set the default PostgreSQL schema in Play? - java

We are using Play Framework 2.1 in our web application. We want to explicitly set the database schema (not public schema) in our PostgreSQL database that's the application's database. How can I set it ?

As far as I know, from what I have tried before. You should define your schema name for each Model you want to. It should be like this:
import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(schema = "schema2")
public class TableOnSchema2 extends Model {
...
}
Maybe this solution would make an additional effort to define each Model with schema name. Because, I don't know whether there is configuration value can be set for specifying default database scheme for the application. But it works for me!
Hope this would help you.. :)

If your tables are all located outside of the public schema, the best thing to do, is to change the search_path for your application user:
alter user your_appuser set search_path = 'schema1';
If you have multiple schemas, you can add all of them:
alter user your_appuser set search_path = 'schema1,schema2,public';
Don't forget to commit this statement. The change will only have affect after the user logs in the next time. Existing connections will not be affected.

Playframework 2.8.x using Scala example:
We can add the below entry in application.conf:
db {
# You can declare as many datasources as you want.
# By convention, the default datasource is named `default`
default.driver = org.postgresql.Driver
default.url = "jdbc:postgresql://localhost/postgres?currentSchema=backoffice"
default.username = "user"
default.password = "password"
}
Play framework will create a default connection pool with these parameters.
Postgres driver basically gives the ability to define the default schema in conneciton url using ?currentSchema=backoffice from version 9.4 onwards.
A Dao object can use this database as below:
import com.google.inject.Inject
import play.api.db.{DBApi, Database, DefaultDBApi}
class PostgresDao #Inject()(backofficeDB : Database) {
val backofficeDb = backofficeDB
//some more methods
}

Related

I am using JAVA Spring Boot REST API and Hibernate/JPA issue is with table name when the name I need to access contains a dot in the name like FOO.BAR

The problem is when hibernate builds the query it ignores the dot and sets the prepared statement "from" to look like
"from foo_bar" when it needs to actually be "foo.bar" So even though it connects to the primary database fine it never finds the table. This is a DB2 schema where it is Database->table.sub-table ( not a join but a naming convention the DBA's use).
I have tried adding the dot in the #Table name prop
A snippet example is like:
#Entity
#Table(name="FOO.BAR")
public class SomeClassName {
}
I tried using the application.properties
spring.datasource.url=jdbc:db2://server:port/dbname and modifying that. Any ideas? Do I need to create my own naming convention or something?
Welcome to stackoverflow Richard.
I am fairly confident that the first value would be considered the schema name.
Perhaps trying the following would work?
#Entity
#Table(name="BAR" schema="FOO")
public class SomeClassName {
}

Dynamic schema in Hibernate #Table Annotation

Imagine you have four MySQL database schemas across two environments:
foo (the prod db),
bar (the in-progress restructuring of the foo db),
foo_beta (the test db),
and bar_beta (the test db for new structures).
Further, imagine you have a Spring Boot app with Hibernate annotations on the entities, like so:
#Table(name="customer", schema="bar")
public class Customer { ... }
#Table(name="customer", schema="foo")
public class LegacyCustomer { ... }
When developing locally it's no problem. You mimic the production database table names in your local environment. But then you try to demo functionality before it goes live and want to upload it to the server. You start another instance of the app on another port and realize this copy needs to point to "foo_beta" and "bar_beta", not "foo" and "bar"! What to do!
Were you using only one schema in your app, you could've left off the schema all-together and specified hibernate.default_schema, but... you're using two. So that's out.
Spring EL--e.g. #Table(name="customer", schema="${myApp.schemaName}") isn't an option--(with even some snooty "no-one needs this" comments), so if dynamically defining schemas is absurd, what does one do? Other than, you know, not getting into this ridiculous scenario in the first place.
I have fixed such kind of problem by adding support for my own schema annotation to Hibernate. It is not very hard to implement by extending LocalSessionFactoryBean (or AnnotationSessionFactoryBean for Hibernate 3). The annotation looks like this
#Target(TYPE)
#Retention(RUNTIME)
public #interface Schema {
String alias() default "";
String group() default "";
}
Example of using
#Entity
#Table
#Schema(alias = "em", group = "ref")
public class SomePersistent {
}
And a schema name for every combination of alias and group is specified in a spring configuration.
you can try with interceptors
public class CustomInterceptor extends EmptyInterceptor {
#Override
public String onPrepareStatement(String sql) {
String prepedStatement = super.onPrepareStatement(sql);
prepedStatement = prepedStatement.replaceAll("schema", "Schema1");
return prepedStatement;
}
}
add this interceptor in session object as
Session session = sessionFactory.withOptions().interceptor(new MyInterceptor()).openSession();
so what happens is when ever onPrepareStatement is executed this block of code will be called and schema name will be changed from schema to schema1.
You can override the settings you declare in the annotations using a orm.xml file. Configure maven or whatever you use to generate your deployable build artifacts to create that override file for the test environment.

How do I configure JPA table name at runtime?

I have an issue where I have only one database to use but I have multiple servers where I want them to use a different table name for each server.
Right now my class is configured as:
#Entity
#Table(name="loader_queue")
class LoaderQueue
I want to be able to have dev1 server point to loader_queue_dev1 table, and dev2 server point to loader_queue_dev2 table for instance.
Is there a way i can do this with or without using annotations?
I want to be able to have one single build and then at runtime use something like a system property to change that table name.
For Hibernate 4.x, you can use a custom naming strategy that generates the table name dynamically at runtime. The server name could be provided by a system property and so your strategy could look like this:
public class ServerAwareNamingStrategy extends ImprovedNamingStrategy {
#Override
public String classToTableName(String className) {
String tableName = super.classToTableName(className);
return resolveServer(tableName);
}
private String resolveServer(String tableName) {
StringBuilder tableNameBuilder = new StringBuilder();
tableNameBuilder.append(tableName);
tableNameBuilder.append("_");
tableNameBuilder.append(System.getProperty("SERVER_NAME"));
return tableNameBuilder.toString();
}
}
And supply the naming strategy as a Hibernate configuration property:
<property
name="hibernate.ejb.naming_strategy"
value="my.package.ServerAwareNamingStrategy"
/>
I would not do this. It is very much against the grain of JPA and very likely to cause problems down the road. I'd rather add a layer of views to the tables providing unified names to be used by your application.
But you asked, so have some ideas how it might work:
You might be able to create the mapping for your classes, completely by code. This is likely to be tedious, but gives you full flexibility.
You can implement a NamingStrategy which translates your class name to table names, and depends on the instance it is running on.
You can change your code during the build process to build two (or more) artefacts from one source.

Unit testing Hibernate with multiple database catalogs

I have an issue testing a Hibernate application which queries multiple catalogs/schemas.
The production database is Sybase and in addition to entities mapped to the default catalog/schema there are two entities mapped as below. There are therefore three catalogs in total.
#Table(catalog = "corp_ref_db", schema = "dbo", name = "WORKFORCE_V2")
public class EmployeeRecord implements Serializable {
}
#Table(catalog = "reference", schema = "dbo", name="cntry")
public class Country implements Serializable {
}
This all works in the application without any issues. However when unit testing my usual strategy is to use HSQL with hibernate's ddl flag set to auto and have dbunit populate the tables.
This all works fine when the tables are all in the same schema.
However, since adding these additional tables, testing is broken as the DDL will not run as HSQL only supports one catalog.
create table corp_ref_db.dbo.WORKFORCE_V2
user lacks privilege or object not found: CORP_REF_DB
If there were only two catalogs then I think it would maybe be possible to get round this by changing the default catalog and schema in the HSQL database to that one explicitly defined:
Is there any other in-memory database for which this might work or is there any strategy for getting the tests to run in HSQL.
I had thought of providing an orm.xml file which specified the default catalog and schema (overiding any annotations and having all the defined tables created in the default catalog/schema) however these overrides do not seem to be observed when the DDL is executed i.e. I get the same error as above.
Essentially, then I would like to run my existing tests and either somehow have the tables created as they are defined in the mappings or somehow override the catalog/schema definitions at the entity level.
I cannot think of any way to achieve either outcome. Any ideas?
I believe H2 supports catalogs. I haven't used them in it myself, but there's a CATALOGS table in the Information Schema.
I managed to achieve something like this in H2 via IGNORE_CATALOGS property and version 1.4.200
However, the url example from their docs did not seem to work for me, so I added a statement in my schema.xml:
SET IGNORE_CATALOGS = true;

How to set application name with JPA (EclipseLink)?

hello everybody i am using JPA with EclipseLink and oracle as DB and i need to set the property v$session of jdbc4 it allows to set an identification name to the application for auditing purposes but i had no lucky setting it up....i have been trying through entitiyManager following the example in this page: http://wiki.eclipse.org/Configuring_a_EclipseLink_JPA_Application_(ELUG) it does not show any error but does not set the application name at all... when i see the audit in oracle it is not being audited with the name i set by code "Customers" but with OS_program_name=JDBC Thin Client it means that the property in the code is not being set properly and i have no idea where the issue is, the code i am using is the following :
emProperties.put("v$session.program","Customers");
factory=Persistence.createEntityManagerFactory("clients",emProperties);
em=factory.createEntityManager(emProperties);
em.merge(clients);
does anybody know how to do it or any idea....
thanks.-
v$session.program is a JDBC connection property, but Persistence.createEntityManagerFactory gets persistence unit properties. There is no direct way to pass arbitrary JDBC property into entity manager.
However, in EclipseLink you can use SessionCustomizer:
public class ProgramCustomizer extends SessionCustomizer {
#Override
public void customize(Session s) throws Exception {
s.getDatasourceLogin().setProperty("v$session.program", "Customers");
super.customize(s);
}
}
-
emProperties.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, "ProgramCustomizer");
You can achive that without SessionCustomizer in persistence.xml:
<property name="eclipselink.jdbc.property.v$session.program" value="Customers" />
FYI: https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CIHHJHHD

Categories