I have a table T with columns defined as usual.
#Entity
#Table(name="T")
public class T {
#Column(name="test_id")
private Long testId;
}
Given entity property "testId", I want to get corresponding DB column name (i.e. "test_id"). How could it be achieved?
Edit 1:
I want to keep this column at separate location with actual DB column name (test_id) than testId. I fetched these values from DB using HQL which have key as entity name (i.e. testId) and I want actual column name in DB.
If I understood your requirement correctly, you want to use HQL while having a consistent name for both DB column and the entity field, like this:
SELECT t.test_id FROM Test t
instead of
SELECT t.testId FROM Test t
There is only one way to do that - renaming the field to test_id. HQL works on entities, not on DB tables, so you must use proper field names in the query.
Since test_id contradicts the usual Java coding conventions, I would advise against it.
EDIT: Getting the annotation attribute value with reflection would work along this outline:
Field field = MyEntity.class.getDeclaredField("testId");
Column a = field.getAnnotation(Column.class);
String columnName = a.name();
I would try to avoid this by any means, but if you're really sure you'll need it, use:
Configuration configuration = sessionFactory.getConfiguration();
PersistentClass persistentClass = configuration
.getClassMapping(T.class.getName());
String columnName = ((Column) persistentClass.getProperty("testId")
.getColumnIterator().next()).getName();
See also Get table column names in Hibernate
Related
I am working on an issue using Java where i have to restrict specific string to store in DB.Example : "NAM" or "nam"
if some data "Vietnam" (Contains "nam") is coming to store in any column, i have to restrict and give some kind of error or notification.
This is easy if we are working one object but if there are multiple tables in the DB and we need to check each and every column data before storing that is painful. i am looking for some generic code that can work on any object.
You could try using Hibernate's check annotations:
#Entity
#Check(constraints = "col1 <> 'Vietnam' AND col2 <> 'Vietnam'")
public class YourEntity {
#Column(name = "col1")
private String col1;
#Column(name = "col2")
private String col2;
...
}
Hibernate should then throw an exception should any entity arrive with a field having the value Vietnam.
If you can't use Hibernate check annotations, a general solution which might work here on the database level would be a check constraint:
ALTER TABLE yourTable
ADD CONSTRAINT cntry_cnstr CHECK (col1 <> 'Vietnam' AND col2 <> 'Vietnam' AND ...);
Attempting to insert a new record where a column contains Vietnam, or attempting to update an existing record's column to Vietnam would then trigger an exception which you could handle in Java.
I am using hibernate's ORM and hibernate-generator to generate the Entity in the annotation way. I need to switch database frequently (dev/release). So, I have to change the entity's annotation every time. I want to know if there is a way to configure it.
#Entity
#Table(name = "my", catalog = "dev_db")
public class MyEntity {
}
As you can see, I've to change the catalog every time. How to configure it according to a jdbc.properties?
You can use Interceptors to modify SQL generated by hibernate.
public String onPrepareStatement(String sql) {
String superSQL = super.onPrepareStatement(newSQLWithNamespace);
//replace all catalog occurencies with desired value in the superSQL
return superSQL;
}
See e.g. Add a column to all MySQL Select Queries in a single shot
Your interceptor can read the catalog value from config and change the SQL.
I am learning hibernate . I am bit confused with hbm2dll.auto update property . Change in model object data type is not changing data type of table in mysql.
Firstly I have created User Pojo with userId as data type int . Initially I have made hbm2dll property as CREATE .
#Entity(name="user")
public class User {
#Id
private int userid;
private String username;
....
}
For persisting data firstly I have created user object like below and saved using sessionFactory .
User user = new user();
user.setUserid(1);
user.setUsername("First User");
Because of above effort User table got created where userid data is int.
But later I changed the pojo’s userid data type to string .
Also I changed hbm2ddl property to update .
So after this change even user object is having string as userid , table userid data type is not changing to varchar . How to change the data type of table using hibernate .
I believe update can not change the data type.
Imagine the field of type string will be change to Integer. What will happen to existing data?
So update (data type update) can not be guaranteed if the table is not empty.
As per my understanding hibernate will not allow you to update field datatype directly,
for this we have to take backup of the current field and then need to create new field and then copy backup data in new field.
And If I am wrong, please correct me too.
If you don't want to loose old data, you can manually do the following:
add new optional column with NEW data type
update the new column with values of the old column (using convert)
drop the old column
rename the new column (not all dialects support this)
mark the column as not-null (optional)
I have a JSONObject in which I am putting keys and values from columns in my database. I want the key name to show up as a custom defined name, while I have it equivalent to the column name in the DB. How do I do this?
For eg, I have -
myObj.put(resultSet.getString(personId), personCarInfo);
While I want it to be -
myObj.put("personId", personCarInfo);
In JDBC, you can query the name of a column using the ResultSets meta data:
String columnName = resultSet.getMetaData().getColumnName(columnIndex);
String columnValue = resultSet.getString(columnIndex); // assuming, its a string
myObj.put(columnName, columnValue);
If I understood you correctly, you want to have mapping between column names and your custom defined names.
You could create simple one-directional mapping using statically initialized hashMap or by using enums.
If you want bi-directional mapping (i.e. be able to restore your table column name string from custom "personId" string) you could use Guava BiMap, for example.
Hope that helps.
I need to set a table name dynamically so that I use query.setText(tname,abc)
e.g: select a.name from :tname where a.id = '2'
I used setText() because when I use setString() it says "tname is a invalid parameter" because I assume that Hibernate adds '' when setting string parameters.
But even setText() does not help and gives the same exception.
How can I set the table name dynamically?
Reply to PSR:
So you mean replace table name as a java string replacement. But then we can not take support of sql injections prevention etc from hibernate right? Also How we bind parameters in hibernate in a situation where like statement,
Eg: name like "%:name%"
This also gives me Illegal argument exception: Parameter does not exist as a named parameter when i try to bind it using query.setString(name,"def");
Hibernate will not do this for you, because it works with PreparedStatements, and you can't prepare a statement where the table being queried isn't known yet.
I don't see why you would be exposing table names to end users, so preventing SQL injection doing a regular string substitution should be easy. You use some sort of business logic to determine the correct table from a list that only you know. The table name isn't coming from user input at all.
Depending on your choice of RDBMS, you may find a discriminator column, or table inheritance with partitioning to be a better way of handling a situation where identical queries are made against different tables.
It is not possible to set table name dynamically.You can set dynamically column names.it is not possible to set table name
try like this
select a.name from '+table name+'where a.id = '2'
In my opinion, There are 2 ways to resolve this issue:
1- If you are using Spring and Hibernate together, you could use SpEL and it would be like #{#entityName} as it is described here
#Entity
public class User {
#Id
#GeneratedValue
Long id;
String lastname;
}
public interface UserRepository extends JpaRepository<User,Long> {
#Query("select u from #{#entityName} u where u.lastname = ?1")
List<User> findByLastname(String lastname);
}
2-You could use CriteriaBuilder like
CriteriaQuery<YourEntity> cr = cb.createQuery(YourEntity.class);
Root<YourEntity> root = cr.from(YourEntity.class);
cr.select(root);
I copied the source codes from the provided links and they are described there much better