How to select property from an entity in a hibernate relation - java

I have an entity class set up in Java, with a many-to-many relationship to another class. However, rather than selecting the entire entity collection, I'd like to select only a property from the child entities. The reason for doing this is that it will lower the amount of data being loaded into the system as I don't always need the entire entity depending on my view.
This is what I have so far:
#Entity
public class Disposition {
...
#ManyToMany
private List<Project> projects;
...
}
This works fine and retrieves a list of Project instances. However, I don't want to get all the Projects for the Disposition; I only want to retrieve Project.name.
The only solution I've been able to come up with so far is using the #Formula annotation but I'd like to avoid this if possible since it requires writing native SQL instead of HQL.
This view is read-only so I don't expect any changes to the data to be persisted.

you can use hql to only get the child's name. It would look something like
"select p.name from Project p where p.parent_id = ?"
you would have to tailor the variable names in that, and use a parameterized query to replace the ? with the id of the parent.
It is common to have tailored DAO methods for exactly this sort of situation.

This is where object relational mapping cannot help you anymore. But you can use the Query API which allows to query arbitrary objects by HQL, not SQL. Isn't #Formula using HQL, too?

It is not Hibernate, but the ebean project could interrest you. Ebean is an ORM project using the JPA annotations and allowing the lazy (partial) loading of objects.
In your example, getting only project names would result in this code:
List<Project> projects = Ebean.find(Project.class)
.select("name") // Only name properties are loaded
.where().eq("disposition", yourDisposition)
.findList();
Then, if you try to get project owner (or every other property), theses properties will be lazy loaded by Ebean.

Check out org.hibernate.criterion.Projections. Given a Criteria you can simply do the following:
criteria.setProjection(Projections.property("name"));

Related

How does Spring JPA derive queries?

I am wondering how does Spring JPA derive queries from methods. As an example, if I was to type
interface CarRepo extends CrudRepository<Car, Long>{ findByCarMake(Make make) }
my query would be automatically derived from the method and would be something as "SELECT * from Car WHERE carMake = xxxxx"
I do understand this concepts but I would like to understand how it works behind the scenes. So, how does it actually derive a query from the method name?
I am aiming at creating a similar thing to suit our needs for a NestJs project so in Typescript not Java and also for an..."unorthodox" database which does not have such support out of the box( Neo4J).
I ll be very grateful to whom can and will help me.
Spring Data JPA derives the queries from the method names in your repository.
There are certain keywords that are reserved by Spring. One the one hand, there are query subject keywords like findBy, existsBy, countBy, etc. which influence the return type of the method. On the other hand, there are operators like and, or, isIn, between, etc. that are applied to the actual query logic.
You start your query with a query subject keyword like findBy and then the fields of your entity (and optionally operators and more fields). You can even have nested fields like findByProviderName where your entity has a field provider which has a field name. If you define an invalid property or property path (e.g. findByProviderNamw), your Spring Boot application would fail on startup. You can find more about defining query methods in the official spring reference.
Spring Data using part tree JPA queries, than map them into SQL query by pre-defined parts.

Spring Data JPA JPQL list in constructor

In my application, a non-standard situation, I have a layer of entity in mysql, layer of dominain in controllers. My domain model contains a few entities, can this be integrated into one JPQL query?
entity layer:
PersonEntity table
EventEntity table
EventVisitorEntity table
PersonEntity many to many EventEntity
EventVisitorEntity interim table
domain layer:
class PersonInfo {
Person person;
List<PersonEvent> personEvent
...
}
Now I get all Person to take their ids and get the PersonEvent, using this query:
#Query("SELECT new domain.PersonEvent(ev.personId,ev.eventId,e.name,ev.state)" +
" FROM EventVisitorEntity AS ev ,EventEntity AS e WHERE e.id = ev.eventId AND ev.personId IN (?1)")
List<PersonEvent> findEventsForPerson(List<Integer> ids);
It is possible to write one query to get persons with an personEvents ?
in the constructor which is below:
public PersonInfo(Person person, List<PersonEvent> personEvents)
Hardly doubt it is possible. JPQL subqueries, which might help you outline personEvents, are allowed only in where and having clauses.
Instead, I'd suggest you to just embrace the query as-is and move the logic of gathering to your DAO tier. This link might be helpful: https://dzone.com/articles/add-custom-functionality-to-a-spring-data-reposito. Declare a method List<PersonEvent> findEventsForPerson(List<Integer> ids), implement custom repository for it, doing all nesessary JPQL queries and combinations there. But beware of N+1 issue.
Also it may be convenient to use entity graphs in such custom implementation.
EDIT: After rereading the spec on fresh mind, I realized that I have mistaken saying that subqueries are allowed only in WHERE/HAVING clauses. It says that it may be used there, which doesn't exclude the opposite. Anyway, even if it is possible, such approach (extracting relation via subqueries) would most probably lead to N+1 issues, unless JPA implementors are smart enough to predict that (I wouldn't count on that anyway).

Is there a way for selecting extra fields - not to be saved - in hibernate?

I want to execute the following sql in hibernate:
SELECT emp.*, utilsPkg.getEmployeeDisplayName(emp.id) FROM employee emp;
So far so good...
The thing is - I need it to be fetched to an entity - so I can update the employee.
Of course that the pl\sql function is not updateable nor part of the actual table...
How can I generate such an entity in hibernate - with a field that is calculated and not updateable?
Many thanks!
Using the #Formula annotation, as explained in the Hibernate documentation:
Sometimes, you want the Database to do some computation for you rather
than in the JVM, you might also create some kind of virtual column.
You can use a SQL fragment (aka formula) instead of mapping a property
into a column. This kind of property is read only (its value is
calculated by your formula fragment).
Use the #Transient annotation on the getter method for that property.
I'm not sure if I fully understand your question, but you can always use Hibernate entity lifecycle callbacks or you can provide it directly in your query:
select new MyEntity(o.column1, o.column2, utilsPkg.getEmployeeDisplayName(o.id)) from MyEntity as o where o.id = 5
Of course you must implement appropriate constructor.

Mapping class to a table without a table name

I have many tables in my DB with exactly the same structure: same columns names and types.
The only difference between these tables is the their names (which I can only know in runtime).
I would like to create a mapping of a class to a table but giving the name of the table only during runtime (no static #Table annotation).
Is it possible?
Is there any other way to achieve my goal?
Directly - no. Because this is not a regular use-case. Normally you should not have dynamcally-generated tables. It is a valid use when you move some records to an archive table (or tables), but otherwise avoid it.
Anyway, you can make that work: make a native query, and map the result to your non-entity object. You will be able to select from any table and transform the result to an object. However, you can't insert or update that way.
Don't think associating or changing the table mapped to an entity dynamically is possible.
You can check #MappedSuperClass, which will allow you to define all fields in a class once and inherit them, so that there is no repetition and entities are empty class with mappings.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1168
If you know the table name dynamically you can always instantiate the mapped class accordingly.

Can I override generated IDs?

I'm using JPA 1, Hibernate and Oracle 10.2.0 and my entities are defined like this:
#Entity
#Table(name="TERMS")
public class Term implements Serializable {
#Id
#GenericGenerator(name = "generator", strategy = "guid", parameters = {})
#GeneratedValue(generator = "generator")
#Column(name="TERM_ID")
private String termId;
}
I have a situation where an XML representation of the Entity (and child entities) will be coming in through a web service to update/replace existing ones. My thought was to just delete the old ones and re-create it from the incoming XML.
However, doing a persist when my entities having existing IDs seem to make Hibernate very angry. So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
Angriness from hibernate:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.idbs.omics.catalog.entity.Term
Thanks
My thought was to just delete the old ones and re-create it from the incoming XML. However, doing a persist when my entities having existing IDs seem to make Hibernate very angry..
Indeed, you cannot assign an Id when it is supposed to be generated, at least not with Hibernate that won't consider the entity as new but as detached (the JPA specification is a bit blurry on the exact rules in this case but that's how Hibernate behaves, see 5.1.4.5. Assigned identifiers for more hints).
So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
To make the delete/insert possible for the web service use case, you'd have to either:
not assign the id ~or~
use a special version of the entity without a generated identifier ~or~
use bulk operations(?)
The alternative if you're actually updating detached entities would be indeed to use a merge (but have a look at these previous questions just in case).
Which approach is better? I don't know, it think it depends on your needs. The later seems more natural if you're updating existing entities. With the former, you'd really get "new" entities (including a new value for the optimistic locking column). Depending on the exact implementation of the process, performances might also vary. And, by the way, what about concurrency (just to mention it, I'm not really expecting an answer)?
You can use EntityManager.merge to save an updated version of the entity. Be aware that this returns another object than the one you pass to it, because it basically fetches the entity from the database, updates the persistent properties from the object you pass and saves the persistent object.
See http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/ for more information on this problem.

Categories