Is it possible with hibernate to set dynamically the name of table and the fields mentioned in the entity class with annotations. I found that is something called naming strategy but I didn't understand it well.
First, I wondered what are the possible solutions to dynamically define the name of table as well as the name of fields?
Second, can someone explain to me the main role of the class ImprovedNamingStrategy and cite an example of use.
From "Java Persistence with hibernate" - You can extend ImprovedNamingStrategy class (Which implements NamingStrategy interface and provides default behavior) and override methods
public String tableName(String tableName) {
return "YourTableName";
}
There are other methods as well.
Hope this helps!!
If you are using spring , u can have a look at SpringNamingStrategy.It already extends the ImprovedNamingStrategy.If required u can override the classToTableName method.If you are using spring-boot , this class name can be externalized with the property spring.jpa.hibernate.naming-strategy .
http://docs.spring.io/autorepo/docs/spring-boot/1.1.5.RELEASE/api/org/springframework/boot/orm/jpa/SpringNamingStrategy.html#SpringNamingStrategy()
Hope this helped.
Related
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 {
}
I am working on a desktop application built using spring framework and one of the part of the application is not working. I found that the repository class does not have any queries with #Query annotation. I haven't encountered it before.
When I try to open the form that uses this, I get an error that the application is not able to connect to the database. The application has 3 databases specified in the application.properties. I have the following questions:
1) How does the following code work without a query specified with #Query annotation. Or where is the query written.
#Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
List<Account> findAccountsByActiveIsTrueAndAccountTypeEquals(String accountType);
List<Account> findAccountsByAccountTypeLike(String type);
}
2) How do we specify which of the database to search for. For example: I have 3 mysql databases currently connected to my application. I wish to access data from DB1 through my Spring boot application through the usual flow of
UI model-> BE Controller/ Service layer -> Repository(Interface) which (usually) has the query written with #Query. How we specify which database this query goes for ?
For your first question I can answer that the JpaRepository has an internal system that analyses the method name you have written and then generates the query that has to be executed to the database.
The #Query annotation is used when the method name and the generated query is not returning the result you wanted to so you specifically tell the compiler which query should be executed.
As mentioned here: https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
2.3.1 Query lookup strategies.
The JPA module supports defining a query manually as String or have it being derived from the method name.
Declared queries
Although getting a query derived from the method name is quite convenient, one might face the situation in which either the method name parser does not support the keyword one wants to use or the method name would get unnecessarily ugly. So you can either use JPA named queries through a naming convention (see Section 2.3.3, “Using JPA NamedQueries” for more information) or rather annotate your query method with #Query (see Section 2.3.4, “Using #Query” for details).
So basically using a naming convention will do the magic.
Also an interesting question and perfect answer can be found here:
How are Spring Data repositories actually implemented?
For your second question you can refer to this example:
https://www.baeldung.com/spring-data-jpa-multiple-databases
It might be a bit complicated in the beginning but eventually it will work.
He use JPA, JpaRepository has CRUD methodes
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
In your application.properties, you can put your mysql DB info
Why this works without #Query?
Because you are using JpaRepository which provides an easy way to get data based on your entity and it's fields.
Here your Account will have active, accountType etc fields. You can use JPA's query creation keywords such as AND, OR, Equals, Like and many more.
Derived queries with the predicates IsStartingWith, StartingWith, StartsWith, IsEndingWith", EndingWith, EndsWith, IsNotContaining, NotContaining, NotContains, IsContaining, Containing, Contains the respective arguments for these queries will get sanitized. This means if the arguments actually contain characters recognized by LIKE as wildcards these will get escaped so they match only as literals. The escape character used can be configured by setting the escapeCharacter of the #EnableJpaRepositories annotation.
How do we specify which of the database to search?
You can create configuration classes based on your databases and define data sources based on that using #PropertySource.
For more details see example here
#Configuration
#PropertySource({ "classpath:persistence-multiple-db.properties" })
#EnableJpaRepositories(
basePackages = "com.baeldung.multipledb.dao.product",
entityManagerFactoryRef = "productEntityManager",
transactionManagerRef = "productTransactionManager"
)
I have a question about hibernate search. I have researched but could not found any answer yet. The simple scenerio;
I have a Foo entity in my project.
class Foo{
Bar bar;
}
This entity can not be annotated with Indexable since it is an external class which comes from jar.
I am able to perform CRUD operations via FooQueryApi . I have Foo records in database. Is it possible somehow integrate this Foo entity and hibernate-search ? If so let me know how could I do this ?
Thanks in advance.
You can use the programmatic API for defining index mappings.
Check out the reference guide for the complete description, it'd look roughly like this:
SearchMapping mapping = new SearchMapping();
mapping.entity(Foo.class)
.indexed()
.property( "bar", ElementType.METHOD )
.indexEmbedded();
Don't forget to add the mapping to the configuration when bootstrapping Hibernate ORM as shown in the reference documentation.
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.
I want to use a simple class with hibernate annotations in a non db project.
I dont wanna dublicate the code and remove annotations.
Is there a way for doing this like using annotations in subclass for parent class's attributes. So i can share the parent class.
Any help would be great, thanks.
Edit:
For example: I have a class:
#Entity
#Table(name = "Sample")
Class Sample{
#Column(name = "attr1")
private String attr1;
// getter setters etc.
}
This class works good for a java project with db dependencies set.
But I serve a restful service with this class.
My client app do not need any db related functions so I dont include any db related jars.
So this is my problem I want to use same classes since both are common for two projects. But I do not need db jars which leads to #Entity annotations to compile errors.
If there is some way to do this, I would be very happy.
Thanks alot.
use hibernate validation groups
Basic Validation Example
create 2 validation groups and use one of them for db project and other for not db project