Using a Spring DataSource and a QueryDsl SQLQueryImpl, how do you specify the schema or set the schema?
Test case is:
Use querydsl-maven-plugin (2.9.0) to connect to DB2 database to generate Q-Classes specifying <schemaPattern>
Spring creates a DataSource bean
DataSource bean is populated by scripts (CREATE SCHEMA FOO, CREATE TABLE FOO.BAR etc)
JUnit test imports DataSource
Query using new SQLQueryImpl(dataSource.getConnection(), Configuration.DEFAULT)
Error:
org.h2.jdbc.JdbcSQLException: Table "BAR" not found; SQL Statement: ...
Note that this test implementation is an H2 database, but the production database is DB2. So far I've tried specifying the schema in the JDBC connection strings to no avail.
com.mysema.query.sql.SQLTemplates has a builder method called printSchema(). Initialise SQLTemplates using the builder() method and call printSchema() before build(). Example to follow:
SQLTemplates templates = OracleTemplates.builder().printSchema().build();
The Schema is encoded in the Q-types. It is accessed in the SQL serialization via the RelationalPath interface http://www.querydsl.com/static/querydsl/2.9.0/apidocs/com/mysema/query/sql/RelationalPath.html
I was able to extend SQLTemplates with my own implementation that called the protected method setPrintSchema(true);.
Related
I have an entity with table name "Transaction". While creating connection using spring orm and hibernate, on startup it successfully creates tables in MySQL but being "Transaction" a keyword in SQL server, it fails on startup.
I cannot change the table name in the code as there is a lot of ripple effects. Hence is there a way where I can define the table name as Transaction in java and intercept or configure in such a way that hibernate while connecting to SQL server escapes the keyword and queries it as "[Transaction]" (escaping it using [])
You can use a naming strategy as explained in this article: https://www.baeldung.com/hibernate-naming-strategy
public class CustomPhysicalNamingStrategy implements PhysicalNamingStrategy {
#Override
public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
return Identifier.toIdentifier(**your table name**);
}
// Other methods
You can try one of the following way:
#Table(name = "`Transaction`");
#Table(name = "\"Transaction\"")
or by setting a property:
hibernate.auto_quote_keyword=true
Long story short
I want to generate DB schema from Hibernate mappings and then replace a specific table with a view of the same name before the application starts.
How can I do this using Spring / Hibernate / DbUnit / JDBC or something else?
My problem in details
I have a few integration tests that are executed against an in-memory database.
There's an AView view in a real database and it's mapped in Java code as
#Entity #Table #Immutable
public class AView {}
I'm generating H2 DB schema from Hibernate mappings for integration tests. And during test application context initialization this view is created as a table. From logs:
Hibernate: drop table AView if exists
Hibernate: create table AView (...)
Some tests fail because of this.
The idea
In order to fix this, I want to make H2 DB schema as similar as possible to the real DB schema. First, I want to generate DB schema from Hibernate mappings, and then replace AView table with AView view.
What I have tried
I have found a similar question: How to execute sql script after db schema generation but before application startup
I created a file schema.sql with DROP TABLE / CREATE VIEW statements. I tried to put the file in src/test/resources/schema.sql but it's not picked up automatically by Spring. I tried to specify this file explicitly in #Sql annotation, but it still doesn't have a visible effect.
I execute the tests via IntelliJ IDEA (if this is important).
My Code
Test and Test application context:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { TestH2Config.class })
#TransactionConfiguration(defaultRollback = true)
#Transactional
public class AViewServiceIT {}
#Configuration
#PropertySource({"classpath:datasource-h2.properties"})
#EnableTransactionManagement
//#Sql({"/schema.sql"})
public class TestH2Config {}
datasource-h2.properties
datasource.driverClassName=org.h2.Driver
datasource.url=jdbc:h2:mem:itest;MODE=MSSQLServer;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS itest\\;SET SCHEMA itest
datasource.username=sa
datasource.password=
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop
Spring framework version is 4.1.9.RELEASE.
You should be able to use the import.sql file in the root of your classpath as a means to have Hibernate execute a set of SQL commands after the schema has been built. Given that you wish to do this specifically for tests only, placing it in the test root classpath should be sufficient.
In hibernate documentation custom types are registered using a Configuration instance. How can I access this instance and register my type using spring boot?
Using #TypeDef for entities works fine, but with a jpa native query i get a "javax.persistence.PersistenceException: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111"
It works with my own dialect and registering via registerHibernateType, but with only one custom type registered to column type Types.OTHER (JDBC type 1111). Any other custom type registration overwrites old one.
The query is simple, only selects a constant value of the given custom type.
Using hibernate 5.0.9 and spring boot 1.4.0.
Same issue
Postgresql driver 42.2.2
Hibernate 5.2.17
I have fixed the issue by adding a custom SQL Dialect.
import java.sql.Types;
import org.hibernate.dialect.PostgreSQL94Dialect;
public class CustomPostgreSQLDialect extends PostgreSQL94Dialect {
public ConnectedWellPostgreSQLDialect() {
super();
registerHibernateType(Types.OTHER, "pg-uuid");
}
}
And configure configure hibrenate to use the new class:
spring.jpa.properties.hibernate.dialect.config=com.mypackage.CustomPostgreSQLDialect
It seems there is no automatic mapping of the result to a custom type.
For postgres, the returned jdbc PGObject contains the column type name (ex: 'tsvector'), but the hibernate custom types knows only the sql type (OTHER in this case), not the db type name, so it cannot do the match.
The workaround is to unwrap the jpa native query and register the returned scalar type (custom hibernate type), ex:
Query query = entityManager.createNativeQuery( "SELECT <SOMETHING> AS res" );
query.unwrap( SQLQuery.class ).addScalar( "res", CustomHibernateType.INSTANCE );
Note that this affects QueryDSL (4.1.4), as there is no mechanism to register the scalar as hibernate custom type, so the jpa native query fails (JPASQLQuery). The workaround in this case is to use a non-jpa native query with a AbstractType registered with QueryDSL, and the conversion will be done automatically.
I have installed postgresql enterprise DB and created some tables
In one of the example. I see the following code.
import org.apache.ibatis.session.SqlSession;
.....
SqlSession session = sessionFactory.openSession();
.....
List list = session.selectList("findAllData-Data", params);
What it does? findAllData-Data means what? I have only created tables in postgresql, but I don't see the table name in above code
Check up the documentation for selectList
"findAllData-Data" is the unique identifier matching the statement to use. Statements are usually defined in some mapper .xml file or in newer versions in annotation of a class, so grep your code for findAllData-Data in order to find the definition.
I created an entity class that has the same properties as project.java, and created a class where I can persist the entity object. Also, I created a database using databases in Netbeans using embedded JDBC. I have the persistence.xml, which provides the properties to connect the db, and is used the persitence class on entitymanagerfactory object. The connection seems fine but I am having Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Column 'PROJECT_ID' cannot accept a NULL value. error.
Is it ok to create the db manually (executing the ddl) or should I create the table in the persistence.xml using property name="javax.persistence.jdbc.url"" value="create-tables ?
Regards
You have to set the value of the column PROJECT_ID.
You can either do this in your code, for example by using the annotations #SequenceGenerator or #GenericGenerator,
or use db features (trigger) to set the id during insert.