Is it possible create column name with white spaces using hibernate? - java

I am building data base system for electronic components. Unfortunatly other programs, that will use some of my tables need to have white spaces in column names. Ive tried in my hbm.xml file something like this with property:
...
property name="partGroup" column="part group" type="string"
...
of course hibernate wont create table with that column name.
Is there a way to do it using hibernate?
Thanks :]

There is a way, enclose the table names or column names with backticks. From the documentation:
5.4. SQL quoted identifiers
You can force Hibernate to quote an
identifier in the generated SQL by
enclosing the table or column name in
backticks in the mapping document.
Hibernate will use the correct
quotation style for the SQL Dialect.
This is usually double quotes, but the
SQL Server uses brackets and MySQL
uses backticks.
<class name="LineItem" table="`Line Item`">
<id name="id" column="`Item Id`"/><generator class="assigned"/></id>
<property name="itemNumber" column="`Item #`"/>
...
</class>

I had solved this problem as follows:
I had create following class:
import org.hibernate.cfg.DefaultNamingStrategy;
public class MysqlAdvancedNamingStrategy extends DefaultNamingStrategy{
#Override
public String columnName(String columnName) {
return "`"+super.columnName(columnName)+"`";
}
#Override
public String tableName(String tableName) {
return "`"+super.tableName(tableName)+"`";
}
}
I had setting as namingStrategy the "MysqlAdvancedNamingStrategy" at previous point.
The advantages of this solution is that you don't need to modify all annotation in you code.
It is also a clean solution because for some reason you may want have an application that access to same database "logic" in two different "database" (so with two style of escaping), with this solution you can intercept what database are you using and you can change the escaping strategy at "execution time", however the annotation are evalutated at "compilation time".
It is also a clean solution if you use Spring framework, with this you can change the escaping strategy without touching java code by setting a bean in session factory with id="namingStrategy" and class="util.MysqlAdvancedNamingStrategy".

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 {
}

Hibernate use column name for property name

I am trying to generate JPA's from hibernate during my build process and everything is working fine except for the naming. The default it looks like is hibernate uses the class type for the property name. Is there a way to make it use the column name in the database as the property name?
for example in my DB i have a column name customer_org_type which references a table called valid_value to make sure the type is valid. When I generate the table it creates a property called:
public ValidValue validValue;
but I would like it to generate as:
public ValidValue customerOrgType;
Is there any way to have that?
I figured it out.
It required an entry in my hibernate.reveng.xml
Since it was a foreign key reference I just had to add the following:
<table catalog="my_catalog" name="user_info">
<foreign-key constraint-name="customer_org_type_id_fk" >
<many-to-one property="customerOrgType" exclude="false" />
</foreign-key>
</table>

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.

How to tell Hibernate annotation #Column to be case-sensitive?

I'm trying to do a simple SELECT query in a table named ECM (in uppercase) on a Sybase db with Hibernate. I've annotated my DBO this way :
#Entity
#Table(name="ECM")
public class RelationshipDbo {
...
}
However, I'm facing a "table not found" error : the generated SQL has the table name in lowercase. I cannot change the database configuration to tell it to be case-insensitive.
I've also tried putting quotes like this :
#Table(name="`ECM`")
and this :
#Table(name="'ECM'")
Result : the quotes are added in the query, but the table name is still converted from uppercase to lowercase.
Technical information :
Hibernate 4.3
JPA 1.2
org.hibernate.dialect.SybaseDialect
Have you guys any idea?
EDIT: Also tried this Hibernate changes #Table(name) to lowercase
Then my columns names and table name are automatically quoted, but the names still get lowercased.
I think I have your answer:
Basically, you need to change the naming strategy for you JPA provider. How you do this will depend on how you setup your project.
In my case, using spring boot data I set a property in my application.properties to
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.EJB3NamingStrategy
Without more details from you I can't give more specifics on how to do this.
My goal is a little different since was trying to create tables upper case and hibernate created them in lower case. Also i was using MySQL not Sybase.
But for me quoting the names like this worked:
#Entity
#Table(name="\"ECM\"")
public class RelationshipDbo {
...
}
Then tables were created upper case. Maybe that helps also for the queries.
What is your Sybase db version ?
SybaseDialect has been deprecated in Hibernate 3.5 and then refactored since Hibernate 4.1 with a bunch of subclasses matching different versions of Sybase. Have you tried one of the subclasses to see if it makes any difference?
org.hibernate.dialect.Sybase11Dialect
org.hibernate.dialect.SybaseAnywhereDialect
org.hibernate.dialect.SybaseASE15Dialect
Try this:
Use backticks as in #Table(name="`ECM`")?
This must work from Hibernate point. If not then problem should be in DB (if i'm not wrong)

JPA one-to-many unidirectional relationship using a join table

I would like to evaluate JPA on an existing project. The database model and the java classes exists and are currently mapped via self generated code. The database model and the java classes do not fit ideally together - but the custom mapping works well. Nevertheless the usage of JPA in general seems worth a try.
As you see I am new to JPA and have to do the work with xml configuration. Currently I am working on a one-to-many unidirectional relationship using a join table (please do not discuss this szenario here).
A (one - relationship owner) <-> AB (JoinTable) <-> B (many)
The tables look like this
A
--
ID
BREF
...
B
--
ID
...
AB
--
A_BREF (foreign key to a reference column in A which is NOT the id)
B_ID
I would like to define a unidirectional one-to-many relationship for class A.
class A {
private List<B> bs;
}
and did it like this:
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref">
<referenced-column-name name="bref" />
</join-column>
<inverse-join-column name="b_id">
<referenced-column-name name="id" />
</inverse-join-column>
</join-table>
</one-to-many>
Althoug this does not force an error it is not working. The problem is that the join table does not work on the ID column of A. The query to select the "B" entities works with the A.ID column value instead of the A.BREF column value to select the entities.
(How) can I make this mapping work (I use eclipselink 2.2.0)?
Thanks for any suggestion!
EDIT:
After looking at a link provided in #SJuan76 answer I slightly modified my mapping to
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref" referenced-column-name="bref" />
<inverse-join-column name="b_id" referenced-column-name="id" />
</join-table>
</one-to-many>
This now causes the following errors (tested with eclipselink 2.1.0 and 2.2.0)
eclipselink 2.1.0
Exception Description: The parameter
name [bref] in the query's selection
criteria does not match any parameter
name defined in the query.
eclipselink 2.2.0
Exception Description: The reference
column name [bref] mapped on the
element [field bs] does not
correspond to a valid field on the
mapping reference.
By the way - if I remove the referenced-column-name="bref" from the definition I get the same exception for the referenced-column-name="id" on the inverse-join-column element. So I doubt that I have understood referenced-column-name correct. I used it to specify the database column name of the tables which are related to the join table. Is this correct?
SOLUTION:
The final error in my szenario was that I did not have the BREF field definied in my class
class A {
private long bref; // missing !
private List<B> bs;
}
and in my orm.xml mapping file for this class
<basic name="bref">
<column name="bref" />
</basic>
I was not aware that I have to define the used join mapping referenced-column-name attributes somewhere in my mapping classes (as I also did not have the join-table itself or the name attributes of join-column/inverse-join-column mapped to a class or class members.)
Also the tip to check the case issue was helpful for me. I feel now quite to verbose in specifying my mapping as I overwrite all default (uppercase) mappings with lowercase values. As my database is not case sensitive I will use upper case notation if special mapping is needed to go with the default.
+1 for all!
Can you try defining the field as "BREF" or the same exact case used if you defined it on the attribute mapping, or you can try setting the eclipselink.jpa.uppercase-column-names persistence property to true. This is likely the issue with "id" when referenced-column-name="bref" is removed, since it is likely the field in the entity defaults to "ID".
In general JPA requires that the foreign keys/join columns reference the primary key/Id of the Entity. But, this should work with EclipseLink, so please include the SQL that is being generated, and if it is wrong, please log a bug.
How is the Id of A defined, is it just ID or ID and BREF?
You can use a DescriptorCustomizer to customize the ManyToManyMapping for the relationship and set the correct foreign key field name.

Categories