I'm trying to use Hibernate to create a table in a SQL Server 2012 database.
I set a number of properties in my Java project's persistence.xml file:
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />
<property name="hibernate.hbm2ddl.auto" value="auto" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.use_sql_comments" value="false" />
... and set the database connection details in when UI create my data source, which is done in a configuration Java class:
dataSource.setDriverClassName(myDriver); // com.microsoft.sqlserver.jdbc.SQLServerDriver
dataSource.setUrl(myUrl); // jdbc:sqlserver://host:port;DatabaseName=dbname
dataSource.setUsername(myUser);
dataSource.setPassword(myPwd);
In the Java class, I also set the default schema when I create the Java Persistence entity manager factory:
final Map<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put("hibernate.default_schema", "mySchema");
entityManagerFactory.setJpaPropertyMap(jpaProperties);
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getObject();
The Java domain class has been annotated as follows:
#Entity
#Table(name = "mytable")
public class MyTable {
...
}
The schema called "mySchema" has been created in the SQL Server database and authorization has been granted to the user specified in the data source.
When I try and run the functionality which should create the table as part of the first run (and populate it appropriately), I get the following error message:
SQLServerException: Invalid object name 'mySchema.mytable'
... and the table has not been created in the schema.
The Hibernate SQL looks like this:
select alias0_.ID as alias1_0_0_
... other columns...
from mySchema.mytable alias0_
where alias0_.ID=?
I'm using version 1.0.0.Final of the hibernate-jpa-2.1-api JAR in my Java project.
Thanks in advance for any assistance.
Related
I'm developing a multi-tenant web app with "Shared Database/Separate Schemas" approach using java, jpa(eclipselink), mysql. My persistence file looks like:
<persistence-unit name="GroupBuilderPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<--- Here goes other properties definition -->
</persistence-unit>
Now here is my EntityMangerFactory and EntityManager:
emfForTenant = Persistence.createEntityManagerFactory("GroupBuilderPU");
EntityManager em = emfForTenant.createEntityManager();
em.setProperty("eclipselink.tenant-id", schemaNameAsTenantId);
Its working fine untill I'm adding any new persistence column in any entity.
Like I've a Entity UserAccount where I've added a new column 'String rentalinfo' :
#Entity
#Multitenant(MultitenantType.TABLE_PER_TENANT)
#TenantTableDiscriminator(type = TenantTableDiscriminatorType.SCHEMA, contextProperty = PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)
public class UserAccount implements Serializable {
...
private String rentalinfo;//Newly added column
...
}
Now after that this the following line is giving error:
em.createQuery("SELECT ua FROM UserAccount ua").getResultList();
The error is:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'RENTALINFO' in 'field list'
So what will be the solution for adding new column (extend table) in this approach?
You are getting this exception because the 'RENTALINFO' column does not exist on your UserAccount table. Under normal circumstances, setting "create-or-extend-tables" will have EclipseLink issue an ALTER to your existing table, adding the new column. However, it would appear ddl generation is not supported for MultitenantType.TABLE_PER_TENANT: https://wiki.eclipse.org/EclipseLink/DesignDocs/Multi-Tenancy/TablePerTenant
Not supported:
Schema generation will not be supported since it requires knowledge of all the tenants (schema's) and further to that, access provision must be set once the tables are created if using schema level table per tenant.
So there is no ALTER and your table does not have the column.
As a side note, you can turn on EclipseLink SQL logging using the following persistence properties:
<properties>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
</properties>
This way, you can see what queries EclipseLink is (or in this case, isn't) executing.
I'm new here, so I hope it's not a stupid question.
I am using a MySQL DB and am trying to use an H2 DB alongside for local tests. I am running into problems when persisting new objects, i.e., objects that do not yet have an Id. It works fine on the running system using MySQL, but currently the local tests in H2 fail with the following exception:
javax.persistence.PersistenceException: org.hibernate.HibernateException: The database returned no natively generated identity value
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:871)
...
Caused by: org.hibernate.HibernateException: The database returned no natively generated identity value
at org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity(IdentifierGeneratorHelper.java:90)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:100)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:58)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2936)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3447)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:203)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:183)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:167)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:320)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:843)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:818)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:822)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:865)
... 33 more
I use the following persistence annotations in the corresponding Java class:
#Entity
#Table( name = "myclass" )
public class MyClassDbo {
private MyClassId id;
#Id
#Column( nullable = false )
#GeneratedValue( strategy = GenerationType.AUTO )
#Type( type=MyClassIdType.FQ_CLASS_NAME )
public MyClassId getId() {
return this.id;
}
...
}
The persistence configuration looks like this. For production:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://#my.db.host#/#my.db.schema#"/>
<property name="hibernate.connection.username" value="#my.db.user#"/>
<property name="hibernate.connection.password" value="#my.db.password#"/>
For local tests:
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.url" value="jdbc:h2:mem:db1;MODE=MySQL;DB_CLOSE_DELAY=-1;MVCC=true;INIT=create schema IF NOT EXISTS generic" />
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
The MySQL DB is setup with the following SQL:
CREATE TABLE MYCLASS
( ID BIGINT PRIMARY KEY AUTO_INCREMENT, ... )
The H2 DB is setup using a testdata.xml
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<MYCLASS ID="1" .../>
</dataset>
with the following code
JdbcDatabaseTester databaseTester = new JdbcDatabaseTester( "org.h2.Driver", "jdbc:h2:mem:db1;MODE=MySQL;DB_CLOSE_DELAY=-1;MVCC=true;INIT=create schema IF NOT EXISTS generic;", "sa", "" );
File file = new File( "testdata.xml" );
databaseTester.setDataSet( new FlatXmlDataSetBuilder().build( file ) );
databaseTester.setSetUpOperation( DatabaseOperation.CLEAN_INSERT );
databaseTester.setTearDownOperation( DatabaseOperation.NONE );
return databaseTester;
and when I look into the H2 DB, everything looks correct to me, the ID column is marked to be the primary key and has a default value which generates an ID.
I am using the following versions:
Java 7
MySQL Connector 5.1.40
Hibernate 4.1.9
H2 1.3.173
DB Unit 2.4.9
I have not found a way to make MySQL and H2 work together here. I have tried different GenerationTypes and the only idea I have right now is to create my own IdentityGenerator which depending on the setup either manually creates an Id for the H2 DB or behaves like the standard IdentityGenerator for MySQL. However, with this I deploy code dedicated for testing into the running system which I would like to avoid.
Thanks for any ideas and suggestions! And please tell me if I forgot any important information.
I have mysql db from which I generated the hibernate entities, now I need to generate in-memory database from these entities for testing. I got this error while trying to run my unit test.
/***
main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42102, SQLState: 42S02
2016-02-16 18:10:47.864 ERROR 29758 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Table "tbl_all_orders" not found; SQL statement:
**/
It looks like the db creation failed.
Here is my testing properties file content:
db.driver: org.h2.Driver
db.url: jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false
db.username: sa
db.password:
hibernate.dialect: org.hibernate.dialect.H2Dialect
hibernate.show_sql: true
hibernate.format_sql: true
hibernate.hbm2ddl.auto: create
hibernate.archive.autodetection=class, hbm
entitymanager.packagesToScan: linda
This is my example for h2 testing. You can alter it a bit and see where it fits in your case. mainly you need to create db tables manually and let your config.xml to have your db included.
You can create .sql file manually and create tables and let the bean to include it if you are using spring.
someTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("testConfig.xml") // <-- this xml you need to include
public class PortDaoImplTest {
private static final Logger log = Logger.getLogger(sysInfoDaoImplTest.class);
#Autowired
private sysInfoDaoImpl sysDao;
#After
public void tearDown(){
portDao = null;
}
#Test
public void testGetPort() {
log.info("Testing getInfo(String id)...");
SysInfo p = sysDao.getInfo("nysdin2039");
assertNotNull(p);
}
testConfig.xml
...xml header...
<!-- h2 driver -->
<bean id="test.dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" >
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:test_mem;DB_CLOSE_DELAY=-1;MODE=ORACLE" />
</bean>
<!-- datasource file -->
<jdbc:initialize-database data-source="test.dataSource">
<!-- table list -->
<jdbc:script location="com/yourPath/h2/schema.sql" />
<jdbc:script location="com/yourPath/h2/test_data.sql" />
</jdbc:initialize-database>
<!-- bean def -->
<bean id="sysInfoDao" class="com.mycompanyName.sysInfoDaoImpl" >
<property name="log" ref="test.log" />
<property name="dataSource" ref="test.dataSource" />
</bean>
....
h2 schema.sql file
drop table IF EXISTS tbl_all_orders;
CREATE TABLE tbl_all_orders
(
your_stuff_ID NUMBER NOT NULL,
your_other_column_stuff VARCHAR2(15) DEFAULT
);
...add your constrains or columns accordingly...
test_data.sql file
INSERT into tbl_all_orders
(your_column_names... , your_other_column_names...)
VALUES
(1, 'values',...);
this is my working configuration for testing (database.properties inside src/test/resources folder)
# DB properties
db.driver=org.h2.Driver
db.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
db.username=sa
db.password=
# Hibernate Configuration
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
# validate: validate the schema, makes no changes to the database.
# update: update the schema.
# create: creates the schema, destroying previous data.
# create-drop: drop the schema at the end of the session.
hibernate.hbm2ddl.auto=create
entitymanager.packages.to.scan=abcde
btw, your unit tests shouldn't be hitting the database.
I'm using Hibernate's JPA-Implementation to access our SQL Server 2012 database.
When trying to select a nvarchar field in a native query, I get an exception "No Dialect mapping for JDBC type: -9".
It looks much like No Dialect mapping for JDBC type: -9 with Hibernate 4 and SQL Server 2012 or No Dialect mapping for JDBC type: -9 but I couldn't find a solution for me there (both are not using JPA).
My database setup:
CREATE TABLE NvarcharExample(
exampleField nvarchar(20) PRIMARY KEY
)
INSERT INTO NvarcharExample(exampleField) VALUES ('hello')
My code:
import java.io.IOException;
import javax.persistence.*;
#Entity
class NvarcharExample {
#Id
public String exampleField;
}
public class NvarcharTest {
public static void main(String[] args) throws IOException, InterruptedException {
String queryString = "SELECT e.exampleField FROM NvarcharExample e";
// establish connection
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistenceUnit");
try {
EntityManager entityManager = entityManagerFactory.createEntityManager();
// access data using JPQL
entityManager.createQuery(queryString).getResultList(); // works
// access data using SQL (native query)
entityManager.createNativeQuery(queryString).getResultList(); // fails
} finally {
entityManagerFactory.close();
}
}
}
My 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="persistenceUnit">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- database connection settings -->
<property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://<servername>:<port>;databaseName=<databasename>" />
<property name="javax.persistence.jdbc.user" value="<user>" />
<property name="javax.persistence.jdbc.password" value="<password>" />
</properties>
</persistence-unit>
</persistence>
With sql logging enable, I get this output in my console
select nvarcharex0_.exampleField as col_0_0_ from NvarcharExample nvarcharex0_
SELECT e.exampleField FROM NvarcharExample e
I'm using
hibernate-core-4.3.10.Final.jar
hibernate-entitymanager-4.3.10.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
hibernate-commons-annotations-4.0.5.Final.jar
sqljdbc41.jar
What I've tried:
using a varchar instead of nvarchar makes it work, but I need nvarchar
using jpql instead of sql works (see my example code), but I need a native query
I tried sqljdbc4.jar in Version 4.0 and 4.1 and I tried sqljdbc41.jar
I head about subclassing the SQL Server Dialect class, but did not have any success with that
I added <property name="dialect" value="org.hibernate.dialect.SQLServerDialect" /> to my persistence.xml (right behind the password property)
I added <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" /> to my persistence.xml
I changed the persistence provider to <provider>org.hibernate.ejb.HibernatePersistence</provider>
Using #Nationalized attribute helped me to map String to nvarchar for MS SQL 2012 without dialect subclassing.
At the same time setting the hibernate.use_nationalized_character_data property to true did not worked for me.
For futher information watch docs National Character Types.
I was able to resolve that issue by subclassing the SQLServerDialect:
package packagename;
import java.sql.Types;
public class SqlServerDialectWithNvarchar extends org.hibernate.dialect.SQLServerDialect {
public SqlServerDialectWithNvarchar() {
registerHibernateType(Types.NVARCHAR, 4000, "string");
}
}
and referencing it in my persistence.xml:
<property name="hibernate.dialect" value="packagename.SqlServerDialectWithNvarchar" />
PS: It seems to be fixed with hibernate 5.1 according to this ticket: https://hibernate.atlassian.net/browse/HHH-10183
I want to use in memory database to query for data in my unit testing, my project is Ibatis (with annotation) for querying actual database which I want to mimic with the help of HSQLDB.
Please help me with how to configure iBatis with HSQLDB.
Also is there any way to these better for unit testing with code which is strongly dependent on database in its functions.
You can make an iBatis sqlMappings.xml config file something like this:
<sql-map-config>
<properties resource="configuration.properties" />
<!--The datasource for you application is configured here: -->
<datasource name = "hsql"
factory-class="com.ibatis.db.sqlmap.datasource.SimpleDataSourceFactory"
default="true">
<property name="JDBC.Driver" value=""/>
<property name="JDBC.ConnectionURL" value=""/>
<property name="JDBC.Username" value=""/>
<property name="JDBC.Password" value=""/>
</datasource>
<!--Declare the SQL Maps to be loaded for this application.
Be sure it's in your classpath. -->
<sql-map resource="maps/beanMappings.xml"/>
</sql-map-config>
plus a congifuration.properties file like this:
JDBC.Driver=org.hsqldb.jdbcDriver
JDBC.ConnectionURL=jdbc:hsqldb:hsql://localhost/myDb
JDBC.Username=sa
JDBC.Password=
and then use it like this:
String resource = "maps/SqlMapConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlMap sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);