I'm trying to use pure JPA 2.1 as a standardized way to generate db schema.
(Underlying database - Derby embedded, persistence provider - eclipseLink)
To check generated scripts I set <property name="javax.persistence.schema-generation-target" value="database-and-scripts"/>
And as a result I got it with some 'sequence' table within.
And although ... ERROR 42X05: Table/View 'SEQUENCE' does not exist.
Can somebody help to understand such a weird behavior?
maven dependencies:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.9.1.0</version>
</dependency>
Entity:
import javax.persistence.*;
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
// getters/setters/constructors
}
main body:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("chapter04PU");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(new Book("Neuromancer"));
tx.commit();
em.close();
emf.close();
persistence-unit:
<persistence-unit name="chapter04PU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>Book</class>
<properties>
<!--<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>-->
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation-target" value="database-and-scripts"/>
<property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.scripts.create-target" value="create.sql"/>
<property name="javax.persistence.schema-generation.scripts.drop-target" value="delete.sql"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:chapter04DB;create=true"/>
</properties>
generated script file:
CREATE TABLE BOOK (ID BIGINT NOT NULL, TITLE VARCHAR(255), PRIMARY KEY (ID))
CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)
Update
After replacing:
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
with:
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
I can 'normally' run app (with exit code 0).
But I still take this weird message while first run (with absent DB).
the second run is clear - no such messages.
Thanks a lot for your suggestion to use <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>!
As for the second problem, the main culprit here is #GeneratedValue(strategy=GenerationType.AUTO) which probably was a default value provided by IDE on entity creation. Given the way org.eclipse.persistence.jpa.PersistenceProvider processes this annotation (leading to the exception about non-existant 'SEQUENCE' table), the simplest solution would be to just use #GeneratedValue(strategy=GenerationType.IDENTITY) instead.
Related
I face following issue while trying to write some JBehave BDD test. Scenario is the following:
Due to an MQ message some specific records should be saved into my database and some should be deleted from it. In my #When step I send the given message and in my #Then step I have some asserts to controll the result.
I face issue with the persist and update methods of Hibernate JPA, because it happens just after my code runs to my #Then step and so I got always false result. When I check it in debug mode, and check every recorsd which should be updated / deteled, they are fine.
I assume my asserts should be executed just after the transaction is committed into the database - but this is not the case as I can see.
Is there a way to set a delay or sleep time between database transactions?
Here is e.g. my delete method in my main project:
public void deleteByAbcId(final String Id) {
getEm().createNamedQuery(TABLE.NAMED_QUERY_DELETE_BY_ABC_ID)
.setParameter(Table.QUERY_PARAM_ABC_ID, Id)
.executeUpdate();
}
And in my BDD project I set up database connection as follows:
public class DatabaseService implements Closeable {
private EntityManagerFactory emf = null;
private EntityManager em = null;
/**
* This creates an entity manager based on the db connection parameters received in the argument
*/
public DatabaseService(Properties configuration) {
emf = Persistence.createEntityManagerFactory("project-pu", configuration);
em = emf.createEntityManager();
em.getTransaction().begin();
}
/**
* Returns the entity manager for the db connection
*/
public EntityManager getEm() {
return em;
}
In my assertion I use the following query to check if the given record was successfully removed from the db:
assertNull(dbHelper.findTableIdBasedOnAbcId(Serenity.sessionVariableCalled(ABC_ID)));
My dbHelper class looks like as following:
public class DbHelper {
private DatabaseService database;
private Configuration config = Configuration.getInstance();
public DbHelper() {
database = new DatabaseService(config.getDbProperties());
}
public String findTableIdBasedOnAbcId(String Id) throws Exception {
String query = "SELECT id FROM TABLE WHERE ABC_ID = ?1";
Query queryResult = database.getEm().createNativeQuery(query);
queryResult.setParameter(1, Id);
List<Long> list = (List<Long>) queryResult.getResultList();
if (!list.isEmpty()) {
return String.valueOf(list.get(0));
}
return null;
}
It always retunr the given record of the database, which gets not deleted.
This is the persistence xml of my main project:
<persistence-unit name="aaa-pu" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/aaaa-ds</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.engine.transaction.jta.platform.internal.WeblogicJtaPlatform"/>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.id.new_generator_mappings" value="false"/>
<property name="tomee.jpa.factory.lazy" value="true"/>
</properties>
</persistence-unit>
And this is the one of my BDD project:
<persistence-unit name="project-pu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.connection.autocommit" value="false" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.generate_statistics" value="false"/>
</properties>
</persistence-unit>
Any idea, how to set transactions not to execute the assert method before the executeUpdate of Hibernate runs?
I tried to call the entityManager.getTransaction.commit method and then start a new one every time but no change.
Is there a way to lock the transaction until the executeUpdate is done and just after that allowing the select query? Or is it possible with JBehave to give a waiting or sleep time between steps?
Thank you.
Using Kundera I wanted to create Tables in Given NameSpace
example
foo:bar
where foo is namespace & bar is tablename
This is not happening with below configuration
Here is my persistent Unit
<provider>com.impetus.kundera.KunderaPersistence</provider>
<properties>
<property name="kundera.nodes" value="ZookeeperIP" />
<property name="kundera.port" value="2181" />
<property name="kundera.client.property" value="User.xml"/>
<property name="kundera.keyspace" value="UserPROFILE" />
<property name="kundera.dialect" value="hbase" />
<property name="kundera.ddl.auto.prepare" value="update" />
<property name="kundera.client.lookup.class" value="com.impetus.client.hbase.HBaseClientFactory" />
</properties>
</persistence-unit>
Here is my User.xml
<clientProperties>
<datastores>
<dataStore>
<name>hbase</name>
<connection>
<properties>
<property name="hbase.zookeeper.quorum" value="ZookeeperIP"/>
<property name="hbase.zookeeper.property.clientPort" value="2181"/>
</properties>
</connection>
<schemas>
<schema>
<name>UNIVERCITY</name>
<tables>
<table>
<name>STUDENT</name>
<properties>
<property name="TTL" value="12345678"/>
<property name="VERSIONS" value="6"/>
<property name="MIN_VERSIONS" value="3"/>
<property name="COMPRESSION" value="GZ"/>
<property name="COMPRESSION_COMPACT" value="GZ"/>
</properties>
</table>
<table>
<name>COURCES</name>
<properties>
<property name="TTL" value="12345678"/>
<property name="VERSIONS" value="6"/>
<property name="MIN_VERSIONS" value="3"/>
<property name="COMPRESSION" value="GZ"/>
<property name="COMPRESSION_COMPACT" value="GZ"/>
</properties>
</table>
</tables>
</schema>
</schemas>
</dataStore>
</datastores>
</clientProperties>
My Entity Classes looks like Below
#Entity
#Table(name = "STUDENT", schema = "UserPROFILE#hbase_pu")
public class Student{
#Id
#Column(name = "StudentID")
String StudentID
#Column(name = "Name")
String Name
}
#Entity
#Table(name = "COURCES", schema = "UserPROFILE#hbase_pu")
public class Cource{
#Id
#Column(name = "CourceID")
String CourceID
#Column(name = "Name")
String Name
}
When I run Test Cases I get
UserPROFILE as table & STUDENT & COURCES as their column families
What I expect is
UserProfile:STUDENT as one table &
UserProfile:COURCE as onother table
I feel now Keyspace in Kundera Persitence.xml takes as TableName & Entities as column family
How to Avoid This ??
I think you are using kundera-hbase
<dependency>
<groupId>com.impetus.kundera.client</groupId>
<artifactId>kundera-hbase</artifactId>
<version>${kundera.version}</version>
</dependency>
For your usecase, you should use kundera-hbase-v2
<dependency>
<groupId>com.impetus.kundera.client</groupId>
<artifactId>kundera-hbase-v2</artifactId>
<version>${kundera.version}</version>
</dependency>
Mapping in kundera-hbase
keyspace ==> hTable
entity ==> column family (a column family for each entity class)
and in kundera-hbase-v2
keyspace ==> namespace
entity ==> hTable (one hTable for each entity)
Check Kundera wiki for more details.
Also, make sure you are using the latest version of Kundera.
I try to test the persistence of some entities with an in-memory H2 DB but I recognized that #SequenceGenerator will never be invoked as it should be, neither when running by build platform, nor when running it with RunAs->JUnit test in Eclipse.
What I can say for sure is that the sequences are generated inside the H2 DB. I can even select them when I connect to this generated H2. So it's definitely not a problem inside H2 but with Hibernate.
(Usually Hibernate automatically assigns an ID when persisting an Entity which needs one).
The entity
#Entity
#Table(name = "HOUSE_USERDATA")
public class UserData {
#Id
#Column(name = "HU_ID")
#GeneratedValue(generator = "SEQ_HOUSE_USERDATA", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(sequenceName = "SEQ_HOUSE_USERDATA", name = "SEQ_HOUSE_USERDATA", allocationSize = 2)
private Long huId;
#Column(name = "HU_DATA")
#Size(max = 1000)
private String m_data;
#ManyToOne
#JoinColumn(name = "HR_ID")
private Registry m_registry;
//more code [...]
}
The reference in the referencing Entity...
#OneToMany(mappedBy = "registry")
private List<UserData> userDataList;
The persistence unit...
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.foo.bar.all.entity</class>
<!-- all entity references -->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.url"
value="jdbc:h2:inmemory;INIT=runscript from 'classpath:testscripts/drop_h2.sql'\;runscript from 'classpath:testscripts/create.sql'"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
</properties>
</persistence-unit>
The invocation in JUnit test...
Registry registry = new Registry();
registry.setClientId("clientId");
List<UserData> userDataList = new ArrayList<>();
UserData userData1 = new UserData();
userData1.setData("User defined data 1.");
userData1.setRegistry(registry);
UserData userData2 = new UserData();
userData2.setData("User defined data 2.");
userData2.setRegistry(registry);
userDataList.add(userData1);
userDataList.add(userData2);
registry.setUserDataList(userDataList);
entityManager.persist(registry);
Registry result = entityManager.find(Registry.class, "clientId");
//MUST NOT BE NULL, BUT IS NULL
assertThat(result.getUserDataList().get(0).getId(), is(not(nullValue())))
Other values are persisted properly. Only the IDs were not generated. (I wonder why this test works at all for all the other values since the ID is defined as NOT NULL in the generated DB, so there should be a persistence exception or something else).
Any ides why the sequence generator does not generate anything (I tried GenerationType.AUTO as well, but no difference)?
When you are doing entityManager.persist(registry) that is what it is going to do, store the Registry and check all the mappings for that class. It will encounter the collection of UserData objects, but because there is no cascade property matching the PERSIST it will not store the UserData objects.
It will only store the top level Registry object. If you want to change this add cascade={CascadeType.ALL} or at least cascade={CascadeType.PERSIST} to the #OneToMany annotation, to tell Hibernate it also needs to check the collection for new elements and persist those.
Or first store the UserData elements, before storing the Registry.
I'm trying to use JPA in Wildfly (which uses Hibernate) with PostgreSQL. I turned on hibernate.show_sql so I can execute the same query in PgAdmin III.
The query is this one (EDIT: issuemanager_sch is the schema. Without it even in PgAdmin the query fails with "relation does not exist" error):
select issuetypet0_.id_issue_type as id_issue1_3_, issuetypet0_.name as name2_3_ from issuemanager_sch.issue_type issuetypet0_
When executed by Hibernate this is showed in both PostgreSQL log and Wildfly log :
relation "issuemanager_sch.issue_type" does not exist character 87
However, when I copy (to grant I'm executing the exact same query), paste and run the query in PgAdmin III it's executed normally and I get the results.
What could possibly be wrong with my configurations? (I tried with both quoted and unquoted queries and the results are the same: fails for Hibernate, works in PgAdmin III)
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="PersistenceManager" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:/datasources/issuemanager_pg</non-jta-data-source>
<class>com.im.issuerepository.domain.IssueTO</class>
<class>com.im.issuerepository.domain.IssueTypeTO</class>
<class>com.im.userrepository.domain.UserTO</class>
<class>com.im.userrepository.domain.GroupTO</class>
<class>com.im.userrepository.domain.RoleTO</class>
<validation-mode>NONE</validation-mode>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.default_schema" value="issuemanager_sch"/>
</properties>
</persistence-unit>
</persistence>
EDIT: issue_type table:
CREATE TABLE issuemanager_sch.issue_type
(
id_issue_type bigint NOT NULL DEFAULT nextval('issuemanager_sch.issue_type_seq'::regclass),
name text NOT NULL,
CONSTRAINT "PK_ISSUE_TYPE" PRIMARY KEY (id_issue_type)
)
EDIT: IssueTypeTO mapping:
#Entity
#Table(name = "issue_type")
public class IssueTypeTO implements Serializable{
#Id
#Column(name = "id_issue_type")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "issue_type_seq")
#SequenceGenerator(name = "issue_type_seq", sequenceName = "issue_type_seq", allocationSize = 1)
private Long idIssueType;
#Column(name = "name", length = 45)
private String name;
// getters and setters
}
I have Hsqldb 1) in memory
<jdbc:embedded-database id="idtSimulatorDataSource" type="HSQL">
<jdbc:script location="classpath:hsql/idt_schema.sql"/>
</jdbc:embedded-database>
2) on server-mode
<bean id="idtSimulatorDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001/idt_simulatordb"/>
</bean>
1) all works properly
2) can't create schema. If I create schema manually, then hibernate create all necessary DDL manipulations and everethyng works properly too.
But I don't know where should I assign property for db initialization script
Here are my persistence file
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="IDTSimulator" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.nxsystems.simulator.idt.domain.IDTAccount</class>
<class>com.nxsystems.simulator.idt.domain.IDTCard</class>
<class>com.nxsystems.simulator.idt.domain.IDTCurrency</class>
<class>com.nxsystems.simulator.idt.domain.IDTCardHolder</class>
<class>com.nxsystems.simulator.idt.domain.IDTProgram</class>
<class>com.nxsystems.simulator.idt.domain.IDTTransaction</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- -->
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.default_schema" value="simulators"/>
<!-- -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<!-- -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/>
<!-- -->
<!--<property name="hibernate.hbm2ddl.auto" value="create"/>-->
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.pool_size" value="10"/>
</properties>
</persistence-unit>
</persistence>
And here are my init file script
DROP SCHEMA IF EXISTS simulators CASCADE;
CREATE SCHEMA SIMULATORS AUTHORIZATION SA -- not work yet
CREATE TABLE SIMULATORS.dirtyhack();
Maybe it would be better to create schema automatically, but I don't know how
UPDATE
I've founf how to launch db init script:
jdbc:initialize-database data-source="idtSimulatorDataSource">
Also I set
<property name="hibernate.hbm2ddl.auto" value="create"/>
But now I've got following error:
11:15:57,337 WARN (main) [JDBCExceptionReporter] SQL Error: -5501, SQLState: 42501
11:15:57,370 ERROR (main) [JDBCExceptionReporter] user lacks privilege or object not found: IDT_CARD
http://publib.boulder.ibm.com/iseries/v5r1/ic2924/index.htm?info/rzala/rzalastc.html
SQLSTATE Value: 42501
Meaning: The authorization ID does not have the privilege to perform the specified operation on the identified object.
What are privileges ?????
UPDATE:
Now I'm really confused.
I look into log. And see following:
/C2/SET SCHEMA PUBLIC DROP SCHEMA IF EXISTS simulators CASCADE
CREATE SCHEMA SIMULATORS AUTHORIZATION SA CREATE TABLE
SIMULATORS.dirtyhack() DISCONNECT /C3/SET SCHEMA PUBLIC DISCONNECT
/C4/SET SCHEMA PUBLIC DROP SCHEMA IF EXISTS simulators CASCADE
CREATE SCHEMA SIMULATORS AUTHORIZATION SA DISCONNECT /C5/SET SCHEMA
PUBLIC DISCONNECT /C6/SET SCHEMA PUBLIC
But I recently changed my init script:
DROP SCHEMA IF EXISTS simulators CASCADE;
CREATE SCHEMA SIMULATORS AUTHORIZATION sa -- not work yet
CREATE TABLE SIMULATORS.dirtyhack1();
Where is my dirtyhack1 () table???
I deleted all mentions about previous launches
UPDATE
I've found the reason.
This block is executed after Hibernate create its DDL manipulations:
<jdbc:embedded-database id="idtSimulatorDataSource" type="HSQL">
<jdbc:script location="classpath:hsql/idt_schema.sql"/>
</jdbc:embedded-database>
And my code contains such lines:
public static Server server = new Server();
#AfterClass
public static void tearDown1() throws Exception {
server.shutdown();
}
#BeforeClass
public static void setUp() throws Exception {
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0", "file:./idt_simulatordb");
p.setProperty("server.dbname.0", "idt_simulatordb");
p.setProperty("server.port", "9001");
server.setProperties(p);
server.start();
Connection conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:9001/idt_simulatordb", "sa", "");
conn.setAutoCommit(true);
Statement st = conn.createStatement(); // statements
String expression1 = "DROP SCHEMA IF EXISTS simulators CASCADE;\n";
(1)String expression2 = "CREATE SCHEMA SIMULATORS AUTHORIZATION SA;";
String expression3 = "CREATE TABLE SIMULATORS.dirtyhack1();";
st.executeUpdate(expression1); // run the query
st.executeUpdate(expression2); // run the query
st.executeUpdate(expression3); // run the query
st.close();
conn.close();
}
That's why I didn't find my dirtyhack1 table, and that's why I got error. Init-database just removed my simulators schema
So there is a question. How to launch init script before Hibernate? Cause if I wouldn't write line (1) then I get error about wrong schema export
You could use the Spring EmbeddedDatabaseBuilder to create the database. Something like this:
new EmbeddedDatabaseBuilder().addScript("classpath:hsql/idt_schema.sql").build();
Then you don't need Hibernate to create the schema for you because it will already exist.