can we use same hibernate annotated pojo class for multiple databases? - java

I have a JAVA POJO class with hibernate annotation for postgresql database.
Now, I have a requirement that we support multiple databases in our application. My question is : Should we use the same class with other databases (Oracle, MySQL, SQL Server) or should I write separate annotated class for each different database ?
Reason: To support special characters we are using database proprietary types instead of hibernate types like
// for oracle
#Column(sql-type="nvarchar2")
private String name;
// for sql server
#Column(sql-type="nvarchar")
private String name;
// hibernate doesn't support different proprietary sql types at same type like this
#Column(sql-type={"nvarchar","nvarchar2"})
private String name;

If it's ok to use nvarchar for all String typed columns by default, you could extend Oracle and MS SQLServer dialects and do something like this:
public class CustomOracleDialect extends org.hibernate.dialect.Oracle10gDialect {
#Override
protected void registerCharacterTypeMappings() {
super.registerCharacterTypeMappings();
registerColumnType(Types.VARCHAR, "nvarchar2");
}
}
public class CustomSQLServerDialect extends org.hibernate.dialect.SQLServer2012Dialect {
public CustomSQLServerDialect() {
super();
registerColumnType(Types.VARCHAR, "nvarchar");
}
}
Then configure these dialects in dependence to the database type used.

The same exact class WILL work with other DB engines, as far as Hibernate is concerned all it cares about is the dialect for the most part. However, some DB engines don't support the identity generation strategy for ID fields for example (from past experience). Depending on what DB engines you are required to work with you may have to get creative a bit but, for the most part, as long as you don't have any DB-engine-specific code in your entity classes, everything should work just fine. I for example switched a project from HSQLDB to SQLite and the only thing that did not work was the identity generation i mentioned earlier. If i were you i would experiment with different dialects and thoroughly test everything.
EDIT
Just saw your edit and that is definitely engine-specific code. In this case you might indeed need different entities to accommodate the specific data type you want to explicitly assign to each column.
Good luck!

Related

Cassandra through java\hibernate

I started learning Cassandra using java, after completing hibernate. I am really surprised by the way in which data is inserted/pulled/deleted from cassandra through java while java is moving backwards these days. Because, hibernate gives a very easy way to communicate with the database, a java developer has no need to know the database query syntax,etc. It is mostly method based operations which are used to communicate with the database. But if i want to communicate with cassandra through java, everything is in an SQL format i mean they named it as CQL but i am really surprised by the way in which things are happening when i compare it to the hibernate.
My question here is, is there any way to communicate/do CRUD operations on cassandra through java in O-R mapping style or can hibernate supports cassandra connectivity?
Cassandra is not a relational database, using a relational mapper isn't going to be as straight forward. There are no joins and it does not support SQL.
The java drivers object mapper is probably closest to what your looking for though. For basic CRUD mappings on Cassandra tables.
See documentation here: https://docs.datastax.com/en/developer/java-driver/3.0/supplemental/manual/object_mapper
ie
#Table(name = "posts")
public static class Post {
private String title;
private String content;
private InetAddress device;
#ClusteringColumn
#Column(name = "post_id")
private UUID postId;
#PartitionKey
#Column(name = "user_id")
private UUID userId;
private Set<String> tags;
...
}
You can perform crud operation with Cassandra using Solr or Spark. Example
Now, do not compare Cassandra with any RDBMS. There is no concept of Relational in Cassandra. So, be careful. If you want to fetch data from Cassandra without much knowledge of Cassandra (similar to Hibernate), you may try Spark:
JavaRDD<Student> studentObj = CassandraJavaUtil.javaFunctions(sc).cassandraTable("schema", "student_table",CassandraJavaUtil.mapRowTo(Student.class)).where("id=1");
Remember, Spark is mainly for Analytics purpose.
I also found some new OGM tools that you may try:
http://hibernate.org/ogm/
https://github.com/impetus-opensource/Kundera
Yes Hibernate is supporting cassandra but it is still under experimental stage!!
so read the below notes carefully before you use it.
This implementation uses CQL3 over the native wire protocol with java-driver. The currently supported version is Cassandra 2.1.
To add the dependencies via Maven, add the following module:
<dependency>
<groupId>org.hibernate.ogm</groupId>
<artifactId>hibernate-ogm-cassandra</artifactId>
<version>5.0.4.Final</version>
To get started you will need to configure the following properties:
hibernate.ogm.datastore.provider
hibernate.ogm.datastore.host
hibernate.ogm.datastore.database
source

How to check properties with Hibernate efficiently?

We are using Hibernate for Object/Relational Mapping. This works fine when loading entire entities. However, often I face the problem that I simply want to check a single attribute or COUNT() table entries based on a certain criteria. For sake of performance, I use Native SQL in those cases instead of loading several objects from database and checking their properties in Java. But having plain SQL queries is error-prone and I feel like it violates the idea of ORM.
So I wonder, is there any ORM approach to check single attributes with Hibernate efficiently?
Example: Let's assume we have two entity beans Order and OrderPosition. We want to check, if an order is partly delivered (i.e. COUNT(OrderPositions WHERE isDelivered = true) > 0).
#Entity
public class Order {
private long id;
private List<OrderPosition> orderPositions;
// ...
}
#Entity
public class OrderPosition {
private isDelivered = false;
// ...
}
(Code is simplified for readability.)

Using native queries but maintaining database independence

With Spring JPA is there an easy way to use native queries but maintaining database independence, for example by using the query which fits best?
At the moment I do this by checking the currently set Dialect from the Environment and call the proper method of my Repository:
public Foo fetchFoo() {
if (POSTGRES_DIALECT.equals(env.getRequiredProperty("hibernate.dialect"))) {
return repo.postgresOptimizedGetFoo();
}
return repo.getFoo();
}
This works but I have the feeling that there is a better way or that I am missing something. Especially because (Spring) JPA allows it to use native queries quite easily but that breaks one of its big advantages: database independence.
As per my understanding, this can be achieved simply by using #Transactional(readOnly=false) and then instead of calling session.createQuery, one can use session.createSQLQuery, as provided in this example.
Your sql can be any of your native query.
Hope this works for you. :)
#Override
#Transactional(readOnly = false)
public Long getSeqVal() {
Session session = entityManager.unwrap(Session.class);
String sql = "SELECT nextval('seqName')";
Query query = session.createSQLQuery(sql);
BigInteger big = (BigInteger) query.list().get(0);
return big.longValue();
}
This is just an idea: I do not know whether it works or not:
My idea would be having subinterfaces, one normal Spring-Data-JPA-interface with all methods for one entiy (without native query hints). Than I would crate a subinterface for every database, that "override" the database specific native statements. (This intrface would be empty if there are no DB specific statements). Then I would try configure Spring-JPA with some profiles to load the right specific interface (for example by a class-name or package-name-pattern)
This seems like a way to complicated way to get queries to work.
If you really want to use optimized queries make it at least transparant for your code. I suggest using named queries and create an orm.xml per database (much like Spring Boot uses to load the schema.xml for a different database).
In your code you can simply do
public interface YourRepository extends JpaRepository<YourEntity, Long> {
List<YourEntity> yourQueryMethod();
}
This will look for a named query with the name YourEntity.yourQueryMethod. Now in your orm.xml add the named query (the default one and in another one the optimized one).
Then you need to configure your LocalContainerEntityManagerFactory to load the specific one needed. Assuming you have a property defining which database you use, lets name it database.type you could do something like the following
<bean class="LocalContainerEntityManagerFactoryBean">
<property name="mappingResources" value="classpath:META-INF/orm-${database.type}.xml" />
... other config ...
</bean>
This way you can keep your code clean of the if/then/else construct and apply where needed. Cleans your code nicely imho.

Can Hibernate be used to store HashMaps of data without classes to represent their structure?

I have pretty much zero experience with Hibernate, though I've used similar persistence libraries in other languages before. I'm working on a Java project that will require a way to define "models" (in the MVC sense) in text configuration files, generate the database tables automatically, and (ideally) be database-backend-agnostic. As far as I can tell from some quick Googling, Hibernate is the only widely-used backend-agnostic Java database library; while I could write my own compatibility layer between my model system and multiple DB backends, that's a debugging endeavor that I'd like to avoid if possible.
My question is: Can Hibernate be used to store data whose structure is represented in some other way than an annotated Java class file, such as a HashMap with some configuration object that describes its structure? And, if not, are there any other relatively-stable Java database libraries that could provide this functionality?
EDIT: Here's a clearer description of what I'm trying to accomplish:
I am writing a data-modeling library. When a certain method of the library is called, and passed a configuration object (loaded from a text file), it should create a new "model," and create a database table for that model if necessary. The library can be queried for items of this model, which should return HashMaps containing the models' fields. It should also allow HashMaps to be saved to the database, provided their structure matches the configuration files. None of these models should be represented by actual compiled Java classes.
I think you could try use #MapKey annotation provided by JPA (not the Hibernate #MapKey annotation, it's pretty different!).
#javax.persistence.OneToMany(cascade = CascadeType.ALL)
#javax.persistence.MapKey(name = "name")
private Map<String, Configuration> configurationMap = new HashMap<String, Configuration>();
I don't believe Hibernate will let you have a Map as an #Entity but it will let you have a custom class that contains a map field:
#Entity
public class Customer {
#Id #GeneratedValue public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Integer id;
#OneToMany #JoinTable(name="Cust_Order")
#MapKeyColumn(name"orders_number")
public Map<String,Order> getOrders() { return orders; }
public void setOrders(Map<String,Order> orders) { this.orders = orders; }
private Map<String,Order> orders;
}
(example from Hibernate docs)
Additionally, you don't have to use annotations (if that is what you're trying to avoid): Hibernate relationships can be described via xml files and there are utilities (maven plugins for example) which can automatically generate the necessary java pojo's from the xml.
Does your model require a relational database? You might consider a database like Mongo that stores any object you can represent with JSON.
you can configure hibernate to work without any entity classes (beans linked to tables),
1. you need to use xml configuration for this. in place of class use entity-name and in place of <property name="something" use <property node="something".
create a hibernate session with entiy-mode as map.
you can use a map to store and retuive information from db. Remember, since you are using map there will be difficulties in 2-way mapping (this was as of 3.3, not sure if its been fixed in later releses)

Replace JDBC in JAVA

I wanted to use Ormlite in my java project so I created two beans :
#DatabaseTable(tableName = "worker")
public class Worker {
#DatabaseField(columnName="wo_id" , generatedId=true , id=true)
private Integer woId;
#DatabaseField(columnName="wo_nom")
private String woNom;
}
#DatabaseTable(tableName = "qualification")
public class Qualification {
#DatabaseField(columnName="qu_id" , generatedId=true , id=true)
private Integer quId;
#DatabaseField(columnName="qu_nom")
private String quNom;
}
When creating the tables, I figured out (too late maybe?) that I needed SQLlite or something like that...
Is it possible to create and use a database from my Java project without using JDBC or anything else of the kind?
without using JDBC or anything else of the kind
JDBC is the way that Java interacts with databases of any kind unless you care to write your own database driver. Assuming you don't want to do that and what you're really looking for is an in-memory or file-based database, use H2. It's superior to both HSQL, which is its predecessor, and Derby.
#RyanStewart is correct that if you are talking about connecting to a SQL database, the was to do with is through JDBC which is how Java communicates with SQL databases like H2, Sqlite, MySQL, Postgres, Derby, etc.. All of those database types are supported by ORMLite.
Is it possible to create and use a database from my Java project without using JDBC or anything else of the kind?
Just for posterity, one way to use ORMLite without JDBC is to implement the backend database interfaces:
ConnectionSource
DatabaseConnection
CompiledStatement
DatabaseResults
This would allow you to implement a backend. But I suspect that you should use JDBC but maybe this information is helpful to others.
An in memory database : http://db.apache.org/derby/
You can use HSQLDB.
HSQLDB - 100% Java Database
Running and Using Hsqldb

Categories

Resources