Lately, I have come across this Spring Data JPA repository method findWithBooksById.
The two classes involved are very basic: Library one-to-many Books, and the method is querying for a library and its books.
I looked at https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.details , but there is no reference to this method pattern (findWith...).
Looking at the query generated, it queries the library table and queries books immediately after. So two queries are called consecutively like if I have called getBooks right after a findById query (lazily initialized books in this case).
Does anyone know how findWith... works in Spring Data JPA?
Does anyone know how "findWith..." works in Spring Data JPA?
It doesn't.
The pattern used is that of find...By....
The second select is probably standard behavior of the JPA implementation used.
It might be that Books get eagerly loaded but can't get loaded in the initial query or that something accesses them and thereby triggers lazy loading.
It's impossible to tell without knowing the JPA implementation and the model classes involved.
Related
After making some search on the web, I think that when using Spring Data JPA Named Queries, we need some extra implementation or definitions comparing to the derived or dynamic queries in Spring Data JPA. In this scene, I am really wondering that do we really need to use Spring Data JPA Named Queries?
Spring Data derived queries are intended (and useful) only for very simple queries. Those queries where you look at the name that you would naturally give such a method and would immediately know how to implement it in SQL or JPQL.
As soon as a query gets a little more complex we shouldn't use derived queries anymore, and often we can't even if we wanted to. For example query derivation doesn't have a way to control the precedence between AND and OR.
For all other queries we need to explicitly code the query one way or the others. And if you don't want your queries mixed with your repository, a named query is a very viable alternative.
I am currently studying Java Serialization. However, I am still confused about its practicality. Generally speaking, when are we supposed to use serialisation in comparison to storing data directly in various database columns?
I think you are confusing Serialization with reading and writing an Object to a database.
As explained in this SO answer Do Hibernate table classes need to be Serializable? JPA objects (which hibernate is) should implement Serializable so that detached entities can be sent to other layers of your application possibly via RMI.
This has nothing to do with how Hibernate reads and writes data to a database. As long as you don't use detached objects you can get away with not having your entities implement Serializable and hibernate will still work just fine.
Hibernate reads and writes to a database via JDBC just like you would if you were writing the SQL queries yourself. If you want to learn more about how hibernate converts your object fields to JDBC methods you can start by looking at Hibernate UserType. Hibernate comes by default with a lot of built in User Types that can convert ResultSet columns of types String, Date, int etc to and from the database. If you need to write your own UserTypes which happens on occasion, you just have to write your own UserType implementation which is pretty simple.
Hibernate-enhanced classes can actually be Serializable. However, you should think about all the outcomes before you use it that way. You may encounter those problems:
if your class has collections of related DB entities, extra queries will be made to load those
if you have bidirectional relation in classes, you can experience a stack overflow
to prevent this behavior, you will need to specify the serialization somehow (e.g. using some #Json* annotations if you serialize to JSON)
if your class only contains IDs, you're fine (but you are losing a lot of Hibernate's goodness)
To understand those problems, you need to know how Hibernate actually works.
The enhancement allows the entity to be partially loaded. E.g., you want to get all books for given user. You get a collection of books, but what you really have is a collection of hibernate-enhanced classes, that only wrap IDs at the moment. Provided that you use the default lazy loading.
Unless you really need something else than IDs, the data will never be loaded. Upon a getter call, background queries are made to obtain the extra information, if needed.
Now, imagine a user has a collection of all his books, as a field. When lazily loaded from DB, there may be nothing at all. However, if you want to serialize it, all getters are called and you get all the books, and transitively, every book author, should the books have a relation to its authors ...
If the relation is bidirectional in the classes, you can even create a cycle that will cause a stack overflow error, where you look who's the book's owner and then you fetch books for him again.
I'm using the mongodb-customer-service-data examples (available at https://github.com/SpringSource/spring-data-document-examples).
The example uses #RelatedDocument to associate domain objects across databases. It allows storing and updating objects well enough.
However, I want to do a Query that has Criteria against both the JPA database (in the example HSQLDB) and MongoDB.
Is this even possible? Is there any example anywhere that proves that it is possible?
Comments not directly related to the issue:
My use case is that our application is an Oracle DB, but we are now starting to receive semi-structured data. The JPA Entities are filterable by a user within certain constraints, but we'd like to expand this capability to the semi-structured data.
There also seems to be competing technologies QueryDSL and EclipseLink, but I can't find anything about doing queries across databases.
In JPA, it doesn't appear to be possible to do cross database queries because there are different PersistanceUnits that are associated with each database. However, mongodb cross-store seems to negate this particular problem.
I never used Spring Data JPA, but if JPA isn't capable of doing this I doubt that Spring Data will offer such capabilities.
I don't know what you understand by mongodb cross-store. So I'll explain shortly what mongodb can and can't do.
With mongodb you can't have queries across multiple collections (tables), so you can't do join with plain mongodb. So #RelatedDocument is a feature which Spring Data offers. Related documents may be either embedded (don't know if Spring Data supports this) or may be some simple DBRef to a document within a different collection (and database). With DBRef you can only query on #RelatedDocument fields like _id, collection and database, but none of the actual referenced documents property.
This said mongodb doesn't allow to search cross database in a single query, as you can't do queries across collections so you can't do this against databases either. The only cross-store functionality you have, is for sharded collections. With this you have you collection distributed across multiple nodes through a shardkey. MongoDB may need to query across all collection shards to fulfill your query. But beside this, what I wouldn't call actually a cross-database function, you have no such capabilities.
If this doesn't help, please explain in more detail what you want todo.
There's an enterprise application using Java + Hibernate + PostgreSQL. Hibernate is configured via annotations in the Java source code. So far the database schema is fixed, but I faced the problem that it needs to be dynamic:I can receive data from different locations and I have to store these in different tables. This means that I have to create tables run-time.
Fortunately, it seems that all of these data coming from the different institutes can have the same schema. But I still don't know how to do that using Hibernate. There are two main problems:
How to tell to Hibernate that many different tables have the same structure? For example the "Patient" class can be mapped to not just the "patient" table, but the "patient_mayo_clinic" table, "patient_northwestern" table, etc. I can feel that this causes ambiguity: how Hibernate knows which table to access when I do operations on the Patient class? It can be any (but only one) of the former listed tables.
How can I dynamically create tables with Hibernate and bind a class to them?
Response to suggestions:
Thanks for all of the suggestions. So far all of the answers discouraged the dynamic creation of tables. I'll mark Axel's answer, since it achieves certain goals, and it is a supported solution. More specifically it's called multi-tenancy. Sometimes it's important to know some important phrases which describes our problem (or part of our problem).
Here are some links about multi-tenancy:
Multi-tenancy in Hibernate
Hibernate Chapter 16. Multi-tenancy
Multi-tenancy Design
EclipseLink JPA multi-tenancy
In real world scenario multi-tenancy also involves the area of isolating the sets of data from each other (also in terms of access and authorization by different credentials) once they are shoved into one table.
You can't do this with Hibernate.
Why not extend your patient table with an institute column?
This way you'll be able to differentiate, without running into mapping issues.
I am afraid you can't do this easily in Hibernate. You would have to generate the Java source, compile it, add it to your classpath and load it dynamically with java.reflection package. If that works, which I doubt it, it will be an ugly solution (IMHO).
Have you consider using a schema less database i.e: NoSQL databases or RDF
databases. They are much more flexible in terms of what you can store in them , basically things are not tight up against a relational schema.
In most environments it is not a good idea to create tables dynamically simply because dbas will not give you the rights to create tables in production.
Axel's answer may be right for you. Also look into Inheritance Mapping for Hibernate.
I agree that its not advisable to create tables dynamically nevertheless it's doable.
Personally i would do as Axel Fontaine proposed but if dynamic tables is a must-have for you I would consider using Partitioning.
PostgreSQL allows you to create ona main table and few child tables (partitions), records are disjunctive between child tables, but every record from any child table is visible in parent table. This means that you can insert rows into any child table you want using just simple insert statement (its not cool but has the same level of complexity as composing and persisting an entity, so its acceptable in your case) and query database using HQL
I haven't worked with hibernate. I have little bit of experience in java. I was going through source of a beast of an java application created by Oracle(Retail Price Management). I was expecting a lot of sql code embedded in there as the application makes heavy use of database. But to my surprise, NO embedded SQL code! so far. I found that it was using what is called as "Hibernate" from the lot of .hbm.xml files. Is it a trademark for java programs using hibernate or maybe I haven't seen the complete codebase?. Could someone enlighten me how this is possible?. Thanks.
Hibernate, as all ORM tools, indeed lessens or eliminates the need to use raw SQL in Java code, due to the following:
many associations between various entities are recorded in the Hibernate mapping, so these are fetched automatically by Hibernate - i.e. if you have an aggregation relationshiop between two classes on the Java side, this may be mapped as a foreign key relationship in the DB, and Hibernate, whenever an instance of class A is loaded, can automatically load the associated instances of class B too,
many queries can be done in Hibernate's own HQL query language, or using its Criteria API.
Under the hood Hibernate does generate SQL to communicate with the DB, but this is not visible on the Java side. It can be seen in the logs though, if it is enabled.
Due to this, programs using Hibernate very rarely need to use JDBC or SQL directly. The exceptions are typically ralted to "tricky" legacy DB schemas which can't be fully handled by Hibernate.
Because that's the whole purpose of using Hibernate or any other object-relational mapping framework.
Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions.
Hibernate generates SQL for all its standard database operations. It understands different SQL dialects, and the mapping files (.hbm.xml) tell it about the database structure so it knows how to construct its queries. There is a showSql setting you can turn on if you want to see it outputting its generated SQL as it runs.
Hibernate is an Object-Relational Mapper (ORM). ORMs are used to hide the ugly details of SQL incompatibility[sic] between databases from your program -- you define your tables and map them to an object hierarchy (the .hbm.xml files) and then Hibernate does the rest. Thus most programs that use Hibernate won't see a single phrase of SQL, unless there's a specific reason to execute a complicated query.
Hibernate is a tool, or technology that takes care of the interaction between the database and application for you. You have to tell the structure of the application and the database to it, this is what is in the .hbm.xml files.
The SQL is generated by Hibernate at runtime (kind of)
Say you have an Fruit class, and objects of this is persisted into a T_FRUIT table.
You say this to hibernate, via the .hbm.xml files. That there is a table T_FRUIT, this table is represented by the Fruit class, and which fields in the Fruit class correspond to which columns in th T_FRUIT table.
And then it knows whenever you are trying to save a fruit, it should insert/update to the T_FRUIT table.
When you want to create an Apple, you create an object of fruit corresponding to apple and save "save this fruit".
Hibernate takes care of persisting it.
You can have relationships defined between tables, and Hibernate is intelligent enough to persist in multiple tables.
When you fetch a fruit, hibernate fetches the details of the fruit and its children also(data from referencing tables). And you can say whether you want fetch all the children
at once, or as and when required.
And so on. Aim is to make your life easier, and code maintainable, easy to read, portable,...
With this info, let me redirect you.