Using Hibernate 3.3.1 and Hibernate Annotations 3.4, the database is DB2/400 V6R1, running that on WebSphere 7.0.0.9
I have the following class
#Entity
public class Ciinvhd implements Serializable {
#Id
private String ihinse;
#Id
#Column(name="IHINV#")
private BigDecimal ihinv;
....
}
For reasons I can't figure, Hibernate ignores the specified column name and uses 'ihinv' to generate the SQL:
select
ciinvhd0_.ihinse as ihinse13_,
ciinvhd0_.ihinv as ihinv13_,
...
Which of course gives me the following error:
Column IHINV not in table CIINVHD
Edit: I switched the log level of hibernate to DEBUG, and I see that it does not process the column annotation for that field. Tried several random things it just doesn't work.
Did anyone had this problem before? I have other entities that are very alike in the way that they are using # in their database field names and that are part of the PK and I don't have this problem with them.
You could try some kind of quoting:
For example:
#Column(name="`IHINV#`")
or
#Column(name="'IHINV#'")
Another option would be to dig in to source code Hibernate dialect for DB2 and see if it contains anything helpful.
Of course, the easiest way would be to remove the hash from column name if possible.
I suspect that the problem is the hash in the column name. A similar question on the hibernate forums suggests that backticks can be useful here.
Related
I've wasted too much time on this ...
I'm using oracle and I have a sequence (MY_TABLE_SEQ) defined which increments by 1.
In my Pojo I have:
#SequenceGenerator(name = "MY_SEQ", sequenceName="MY_TABLE_SEQ", allocationSize=50)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MY_SEQ")
This gives me a unique constraint issue. From my understanding I need to set the following property:
hibernate.id.new_generator_mappings=true
I've tried setting in my hibernate.cfg.xml file but it does not seem to make any difference. I've come across server post to place in persistance.xml but this is a standalone app, no webcontainer.
Setting allocationSize=1 works but of course it hits the db on each insert to get the next sequence. Setting the above property is suppose to resolve it.
I haven't tried Oracle, but I had similar issues to yours inserting into an AS400 DB2 table.
I had to remove the identity flag on the id column on DB2 table - and instead used a custom jpa/hibernate sequence generator. This is set up on the pojo/entity annotation of the #ID entity field as you've done.
DB2 had been giving me errors about missing SYSIBM.SYSSEQUENCES table, so evidently hibernate (version 5.2), doesn't recognize the native DB2 identity designation. A custom sequence was and effective workaround.
On the #ID entity field:
#GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
#TableGenerator(name = "table", allocationSize = 20)
This example allocates a pool of 20 sequence numbers each time it queries the table.
Next, create the required table Hibernate needs with columns that match the hibernate5 API - must be in lower case ... so put quotes around the names to work around the auto-upper casing that DB2 defaults to. The API will error out if these names are in caps.
Table:
"hibernate_sequences"
example of 2 Columns used:
"sequence_next_hi_value" (integer, not nullable, 0 default)
"sequence_name" (character, sample length 20, not nullable, natural default)
In the configuration code for the dialect used - ex: Spring Boot programmatically, add these properties:
properties.put("hibernate.supportsSequences","false");
properties.put("hibernate.id.new_generator_mappings","false");
and in the *.properties file:
spring.jpa.properties.hibernate.dialect.supportsSequences=false
spring.jpa.properties.hibernate.id.new_generator_mappings=false
Database systems are case-sensitive for schema/table/field names. Also watch for typos everywhere, incl. property names.
Be sure your pojo/entity only contains private fields that will be mapped to the table. Static finals such as serialVersionUID are ok.
I will be doing someething similar for SQL Server soon.
For MySQL, I had no issues using an identity column as defined in a table ID field to insert records, so didn't have to make all these changes. A simpler setup since hibernate recognizes the identity designation in MySQL.
#GeneratedValue(strategy=GenerationType.IDENTITY)
was all that was needed in the pojo.
I'm a newbie at all this, so always looking for better ways ... but this worked for now.
I set the property like this in the hibernate.cfg.xml file and it works !
<property name="hibernate.jpa.compliance.global_id_generators" value="true"/>
I have been facing this weird exception while trying to persist some values into a table using Hibernate in a Java application. However this exception occurs only for one particular table/entity for rest of the tables i am able to perform crud operations via Hibernate.
Please find below the Stacktrace and let me know if this is anyway related to java code is or its a database design error.
2016-04-28 11:52:34 ERROR XXXXXDao:44 - Failed to create sessionFactory object.org.hibernate.tool.schema.extract.spi.SchemaExtractionException: More than one table found in namespace (, ) : YYYYYYY
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.XX.dao.XXXXXXXDao.main(XXXXXXXXDao.java:45)
Caused by: org.hibernate.tool.schema.extract.spi.SchemaExtractionException: More than one table found in namespace (, ) : YYYYYYY
at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.processGetTableResults(InformationExtractorJdbcDatabaseMetaDataImpl.java:381)
at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.getTable(InformationExtractorJdbcDatabaseMetaDataImpl.java:279)
at org.hibernate.tool.schema.internal.exec.ImprovedDatabaseInformationImpl.getTableInformation(ImprovedDatabaseInformationImpl.java:109)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.performMigration(SchemaMigratorImpl.java:252)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:137)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:110)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:176)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:458)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at com.xx.dao.zzzzzzzzzzzzDAOFactory.configureSessionFactory(zzzzzzzDAOFactory.java:43)
at com.xx.dao.zzzzzzzzzzzzDAOFactory.buildSessionFactory(zzzzzzzzzDAOFactory.java:27)
at com.xx.dao.XXXXXXXXDao.main(XXXXXXXXDao.java:41)
Thanks in advance for your help
I have had the same problem and was able to dig down to the code to find out the cause, at least in my case. I don't know whether it will be the same issue for you but this may be helpful.
From your stack trace I can see you have the hibernate.hbm2ddl.auto set to upgrade the schema. As part of this, it is trying to look up the metadata for all the tables hibernate knows about and for one of them getting an ambiguous answer because the metadata query is returning more than a single row of table or view metadata.
In my case this was caused by our naming convention for tables. We had a table called (say) "AAA_BBB" for which this was going wrong. Now the use of an underscore in the table name is perfectly acceptable as far as I am aware and is quite common practice. However the underscore is also the SQL wildcard for a single character; looking in the code for the database metadata I can see it is doing a "WHERE table_name LIKE ..." in DatabaseMetaData.getTables(...) method, which is what hibernate is using here.
Now, in my schema I also had a second table called "AAA1BBB" and hence both of these matched the metadata lookup and so it returned a metadata row for each of these tables. The hibernate method is written to just fall down if the result set from the table metadata lookup returns more than one row. I would guess it should examine the available row(s) and find if there is one which is an exact match with the specified table name.
I tested this for both Oracle and MySQL with the same result.
Seems the property hibernate.hbm2ddl.auto set to update is causing the issue here. Try removing it from your hibernate config xml.
This will work:
Check your database schema/s and your database user privileges;
Hibernate update mechanism may fail with this exception if there is a another database schema/user with the same table name, and the db user has the sufficient privileges to view this table.
So in your case, the table 'YYYYYYY' may be found in more than one database user/schema, and your db user has 'DBA' privileges.
To solve this you can either find and delete the ambiguous table or remove the user's redundant privileges.
Another situation may be occurred except whatever dear RichB has been stated.
in ORACLE every user has separate schema ,
Therefore probably there is tow tables with the same name in two different schemes
then you should specify your default schema in persistence.xml with below property
<property name="hibernate.default_schema" value="username"/>
Use catalog value with #Table, i.e.:
#Entity
#Table(**catalog = "MY_DB_USER"**, name = "LOOKUP")
public class Lookup implements Serializable {
}
I don't have this error now.
Hope this work.
We had a Spring Data / JPA application and this error started happening after upgrading to Postgres 10.6 (from 10).
Our solution was as follows, in our JPA configuration class: note the new commented line,
props.put("hibernate.hbm2ddl.auto", "none"); //POSTGRES 10 --> 10.6 migration
Class:
#Configuration
#EnableJpaRepositories(basePackages = "app.dao")
#ComponentScan(basePackages = { "app.service" })
#EnableTransactionManagement
public class JpaConfig {
#Autowired
DataSource dataSource;
#Bean
public Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<String, Object>();
props.put("hibernate.dialect", PostgreSQL95Dialect.class.getName());
props.put("hibernate.hbm2ddl.auto", "none"); //POSTGRES 10 --> 10.6 migration.
return props;
}
So after having the same issue, it turns out that I needed to update my OJDBC driver from ojdbc6 to ojdbc8. Hopefully this helps.
I have same issue with such configuration
#Entity
#Table(name = "NOTIFICATION")
public class Notification {
...
}
issue was resolved for me when I moved table name from #Table to #Entity
#Entity(name = "NOTIFICATION")
#Table
public class Notification {
...
}
Simply, if u are using two schemas then u will get this error. To resolve this error u can use these steps :
1. You need to delete extra schema.
2. Or u can define default schemas or that schema are u using.
spring.jpa.properties.hibernate.default_schema=nameOfSchema
and
jdbc:postgresql://localhost:5432/databaseName?currentSchema=nameOfSchema
I also came across this issue. Here is my solution:
the error:
https://gist.github.com/wencheng1994
I solve that. It mainly because the db account has a higher authority. I set the "hibernate.hbm2ddl.auto=update", So when hbm2ddl works, it tried to find all exists shcema I defied. But there is two schema exist the table with the same name. then the db account can find that. so it found "more than one table in the namespace"
All I need to do is to make the db account lower authority so that it can not find table in other schema. (one shcema relation one db account).
Similar to this problem:
ORA-00904: : invalid identifier Issue with Hibernate Dependent objects program
I'm trying to do batch inserts using hibernate. Whenever I try to do a session.save or session.saveOrUpdate, hibernate complains that I have an invalid identifier
Stack output
2015-11-20 14:17:37 ERROR : ORA-00904: "USERATTRID": invalid identifier
Entity
public class Attribute {
#Id
#GenericGenerator(name = "increment", strategy = "increment")
#GeneratedValue(generator = "increment", strategy = GenerationType.SEQUENCE)
private int USERAttrID;
private long userNumber;
private String attribute;
private String value;
private String description;
private LocalDateTime updatedDate;
private LocalDateTime createdDate;
The database looks like this after hibernate applies its improved naming convention
USER_ATTRID
ATTRIBUTE
USER_NUMBER
DESCRIPTION
VALUE
CREATED_DATE
UPDATED_DATE
If I use repository.save then the code works fine. The crud repository seems to know how to map my entity to the database, but hibernate's session does not.
I see a few solutions here:
1. Use hibernate's default default naming strategy. Tables get named things like USERATTRID. I'm not sure what implications this has other than making columns harder to read.
2. Combine hibernate with crudrepository using the tutorial here
http://frightanic.com/software-development/jpa-batch-inserts/
3. Figure out how to get hibernate's session.save to use the improvedNamingConvention mapper. Can anyone help me with this or provide me another suggestion?
4. I guess I can also manually map the columns :/. Ugh this is messy, you now have to manually do all the conversions on dates :/
It would be good to know how you are actually getting the session?The most likely cause that comes to mind is that when you using the hibernate session it is actually not built using the same configuration that was used to build the entity manager that CrudRepository uses underneath.
Ends up being more trouble than it's worth as you stop using hibernate jpa's defaults and all the things spring-data provides you out of the box
Stupid. The tutorial doesn't even use crudRepository
Same as 1
Same as 1
Instead I'm banging my head against a wall trying to get a simple batch process to insert
I'm currently migrating some existing code from Hibernate 3.2 to Hibernate 3.6.10.Final
(and also from Spring 2.0 to Spring 3.1.2 by the way).
I have an issue with some integration tests running against H2 database, verifying that some fields are not nullable.
- I test that an attempt to insert a null String into a field marked as nullable=false ends with an Exception
- I checked that the schema is correctly created : the column is not nullable.
Using H2 (with MySQL mode), nullable constraint is ignored : an empty String is inserted in database.
I don't reproduce the case if I run my test against a MySQL database.
It worked before with Hibernate 3.2
For example, if I have a class Person :
#Entity
class Person {
#Id
#GeneratedValue
private Long id;
#Column(nullable=false)
private String name;
//getters and setters
}
And then I have a test (still using JUnit3, I'll migrate this later) :
#ExpectedException(value=DataIntegrityViolationException.class)
public void testPerson_NameCantBeNull() throws Exception {
// Given
Person person = new Person();
person.setName(null);
// When
getHibernateTemplate().persist(person);
//Flush and clear session
}
I could fix this by replacing nullable=false by #NotNull annotation but I don't want to replace it in my huge code base as I wouldn't expect the same Exception.
I had a quick look into H2Dialect class and JIRA issues in Hibernate but I didn't find anything.
Does anybody know where it comes from ?
EDIT :
Some additional informations, I added the TRACE level in Hibernate logs.
When I insert null and the field is marked with #Column(nullable=false), I have the following log :
2013-01-16 15:57:52 TRACE [BasicExtractor] found [] as column [NAME1_3_]
When I insert null and the field is not marked with #Column(nullable=false), I have the following log :
2013-01-16 15:57:52 TRACE [BasicExtractor] found [null] as column [NAME1_3_]
EDIT (22/01/13) :
I still didn't found where the problem exactly come from, but I found out that it is tied to MySQL mode with H2 : if I disable MySQL mode, Hibernate doesn't try anymore to replace my null Strings by empty Strings.
But I can't do this since some other pieces of code are tied to MySQL syntax.
Any idea ?
I didn't have enough time to digg in Hibernate and MySQL dialect, so I moved to Java Validation Framework, using #NotNull annotation.
It does the job and meets one of our other requirement : a part of our model is used in a Grails application and we want to use constraints to validate part of CRUD operations (not possible with pure javax.persistence annotations).
Abridged version of my schema:
utility_company
id int not null -- PK
name varchar(255) not null
utility_settings
utility_id -- FK to utility
use_magic tinyint(1) not null default 0
There is a one-to-one mapping between these two tables. Setting aside the fitness of this design, I want to Map the data in both of these tables to one object. In Hibernate/JPA, this is allegedly done as follows:
#Entity
#Table(name = "utility_company")
#SecondaryTables({
#SecondaryTable(
name = "utility_settings",
pkJoinColumns = {
#PrimaryKeyJoinColumn(
name="utility_id", referencedColumnName="id")
})
})
public class UtilityCompany extends AbstractEntity {
And so forth.
Every #Column includes the appropriate table name.
When I deploy, I get this error:
Cannot find the expected secondary table:
no utility_company available for poscore.model.UtilityCompany
The utility_company table is definitely there (a previous version only maps UtilityCompany to the utility_company table; I'm adding the utility_settings).
Found numerous forum posts with this exact problems and no answers. I've also tried various allegedly legal forms of specifying the #SecondaryTable all of which have the same effect.
Anyone successfully use #SecondaryTable, and, if so, seen this?
"Every #Column includes the appropriate table name."
Try removing the explicit table name for the first table name columns, only specifying it for the secondary table columns. Did the trick for me.
Your mappings are correct IMHO, and runs fine with DataNucleus AccessPlatform as the JPA implementation. Maybe Hibernates log tells you more ?
--Andy DataNucleus