Hibernate mapping #manytomany - java

I got 3 tables: Bus, Driver and BusDriver and I need to get bus entity with set of drivers. I have already understood how to do this but there is a date field in BusDriver and I need to include it in set. For example I got {bus_id, bus_model, ... {driver1, driver2}} but I need {bus_id, bus_model, ... {{driver1, date}, driver2, date}}

You'll need to map the BusDriver table to an entity to get this attribute.
You should do something like this exemplo

Generally you would do this by explicitly mapping BusDriver as an entity, then having one or both other entities map BusDriver as ManyToOne or OneToMany (as appropriate). Your model interface itself can obscure this if necessary by returning a Set or List of Bus (or Driver) instead of the mapping class.

Related

How to customize hibernate #ElementCollection envers audit table name?

I'm currently using Hibernate & Envers version 5.2.9.Final. I want to use #ElementCollection with a custom table name for both the collection and the audit table.
What I know so far is that modifying default table names has a variety of annotations to work with: For the entity itself there are the annotations #Table and #SecondaryTable as well as the corresponding envers annotations #AuditTable and #SecondaryAuditTable. For changing the table name of an element collection there is the #CollectionTable annotaion. I have not been able to find a corresponding envers annotation so far. So my question is:
How can I change the name for a hibernate #ElementCollection envers audit table?
Additional info
In the hibernate envers ticket which tracks the adding of auditing support for element collections, the same question was asked back in 2013 but not answered.
A code snippet to make my setup clear:
#Entity
#Table(name = "\"user\"")
#SecondaryTable(name = "\"user_secondary\"")
#Audited
#AuditTable("\"user_audit\"")
#SecondaryAuditTable(secondaryTableName = "user_secondary",
secondaryAuditTableName = "\"user_secondary_audit\"")
public class User {
// ... stuff like id and other fields ...
#ElementCollection
#CollectionTable(name = "\"user_references\"")
private Map<String, Long> references = new HashMap<>();
// TODO FIXME how to get a custom name for the audit table?
// ... more stuff like getters and setters
}
Hibernate generates all tables as intended, yet the collecction audit table is named 'user_references_AUD' while I would like to get the name 'user_references_audit' like for the other tables.
I'm also aware of the global settings affecting the audit table prefix or suffix, but that is only a last resort for my use case.
Update
As suggested I added a feature request to Hibernate JIRA.
That is because Envers has no complement for #CollectionTable.
You are welcomed to add a JIRA requesting that we add a complementing annotation and I can look at what is needed to add the functionality. Just at a glance, it shouldn't require too much as it merely needs to feed into the generated Envers entity table name for the collection middle entity.

JDO - 1-N unidirectional relation using annotations - Column name?

I'm using JDO (with Datanucleus implementation) for a new project for the first time, and I'm having troubles defining 1-N unidirectional owned relation using JDO annotations. What I need is to have a collection of Subitems in an Item, such that a Subitem doesn't have a reference to the owner:
#PersistenceCapable(detachable = "true")
public class Item {
...
#Persistent(defaultFetchGroup = "true")
Collection<Subitem> subitems;
...
}
It's all well and good, but how can I define which existing RDBMS column the relation maps to? AFAIK an owned 1-N is realized in a DB by creating a non-nullable table column in a child table but I don't have (and don't want) a parent reference class field in a Subitem which I can then decorate with #Column(name="...") annotation.
And how to properly use #ForeignKey annotation in JDO3? The annotation accepts the name of the FK constraint but not the corresponding FK table and column specification. By definition a FK is a ref. constraint between two tables based on a common key, but I can't seem to specify the other table and a common key(#ForeginKey at Datanucleus JDO docs ).
Edit:
#Element(column="...") annotation should be used instead:
#PersistenceCapable(detachable = "true")
public class Item {
...
#Persistent(defaultFetchGroup = "true")
#Element(column="itemId")
Collection<Subitem> subitems;
...
}
As it's clearly stated in the documentation links in the answer.
JDO (or JPA too for that matter) doesn't have "owned" relations, just relations (it is a term I've only ever heard of in relation to GAE's datastore, and you're not using that).
DataNucleus docs defines all such relations adequately IMHO so just navigate the menu from where you got to, for example
http://www.datanucleus.org/products/accessplatform_3_1/jdo/orm/one_to_many_collection.html#fk_uni
http://www.datanucleus.org/products/accessplatform_3_1/jdo/orm/constraints.html#fk

is mappedBy in hibernate defined as per schema definition or is it defined logically?

I have the following situation:
One Destination can have Many Aliases
Logically: I would like Destination to be the owner of this relationship, since if there was no destination, alias would not hold any meaning.
However, the database schema is like this:
DestinationAlias has idDestination as the Foreign Key and thus the #JoinColumn in hibernate annotation would be on DestinationAlias:
Destination:
#OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.ALL}, mappedBy = "mainCity")
public Set<DestinationAlias> getAliases() {
return aliases;
}
DestinationAlias:
#ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="IDDESTINATION", nullable=false)
public Destination getMainCity() {
return mainCity;
}
From this definition, DestinationAlias is the owner of this relationship since the mappedBy is an attribute on Destination class.
Does hibernate require me to follow the database schema and mark entity as the owner of the relationship or can it be done based on Logical reasons ?
Ownership affects how hibernate would model the underlying database tables. If you omit the mappedBy attribute, hibernate would generate a join-table (like for an M-M relationship) between Destination and DestinationAlias, instead of a simple join column. Other than that, I'm curious as to what your actual issue is here. Is this purely cosmetic, or are there functional issues in play for you here?
EDIT: as this seems to be a purely cosmetic issue, my advice is to just accept the Hibernate semantic. While I agree that it might appear counter-intuitive that Hibernate would call DestinationAlias the "owner", that is just the nomenclature Hibernate decided on. It's not unique either and it comes from the notion that the "owner" is where the join-column resides.
Don't waste time trying to force hibernate to conform to your definitions when you don't have to.

Load Entity from View in JPA/Hibernate

I have an application which uses Spring and Hibernate. In my database there are some views that I need to load in some entities. So I'm trying to execute a native query and load the class withthe data retrieved from the view:
//In my DAO class (#Repository)
public List<MyClass> findMyEntities(){
Query query = em.createNativeQuery("SELECT * FROM V_myView", MyClass.class);
return query.getResultList();
}
and MyClass has the same fields as the column names of the view.
The problem is that Hibernate can't recognize MyClass because it's not an entity (it's not annotated with #Entity)
org.hibernate.MappingException: Unknown entity
If I put MyClass as an entity the system will put try to create/update a table for that entity, because I have configured it :
<property name="hibernate.hbm2ddl.auto" value="update"/>
So I come into these questions:
Can I disable "hibernate.hbm2ddl.auto" just for a single entity?
Is there any way to load the data from a view into a non-entity class?
If not, what would be the best way in my case for loading the data from a view into a class in hibernate?
Thanks
Placed on your class
#Entity
#Immutable
#Subselect(QUERY)
public MyClass {....... }
Hibernate execute the query to retrieve data, but not create the table or view. The downside of this is that it only serves to make readings.
You may use axtavt solution. You may also just execute your query, and transform the List<Object[]> it will return into a List<MyClass> explicitely. Or you may map your view as a read-only entity, which is probably the best solution, because it would allow for associations with other tables, querying through JPQL, Criteria, etc.
In my opinion, hibernate.hbm2ddl.auto should only be used for quick n' dirty prototypes. Use the hibernate tools to generate the SQL file allowing to create the schema, and modify it to remove the creation of the view. Anyway, if it's set to update, shouldn't it skip the table creation since it already exists (as a view)?
You can use AliasToBeanResultTransformer. Since it's a Hibernate-specific feature, you need to access the underlying Hibernate Session:
return em.unwrap(Session.class)
.createSQLQuery("...")
.setResultTransformer(new AliasToBeanResultTransformer(MyClass.class))
.list();

Efficiently determining the IDs of entities referenced via OneToMany relationship

Let's say I have a Hibernate entity that declares a OneToMany relationship to a different entity:
#Entity
public class SomeEntity {
#OneToMany(fetch = FetchType.LAZY)
private List<OtherEntity> otherEntities = new LinkedList<OtherEntity>();
[...]
}
When mapping SomeEntity to the corresponding DTO, all I need are the IDs that identify OtherEntity as primary key (i.e., I am not actually interested in OtherEntity instances).
Does Hibernate support this pattern, i.e., only retrieving the IDs of entities referenced via a OneToMany relationship?
I cannot influence how SomeEntity is retrieved (i.e., I have an existing SomeEntity instance retrieved within te scope of the current Hibernate session), but let's assume that lazy loading has not yet taken place, so just retrieving the child objects' IDs (rather than the complete objects) would actually yield a performance benefit.
Well, if you only need the entities' ids and you want to be economical about it, when you get those entities from the database you should state in your query that you only want to get the ids of each entry, using projections, something like :
SELECT Entity.id as entity FROM Entity WHERE ...
This will return an array of objects of the same type as Entity's id field type.
You can try obtaining the primary key without accessing the entity itself (without otherEntities.get(0).getId()). To do this you can use the PersistenceUnitUtil class:
PersistenceUnitUtil#getIdentifier(yourEntity)
The PersistenceUnitUtil can be obtained from the EntityManagerFactory. So it could be something like:
EntityManager em = ...
PersistenceUnitUtil = em.getEntityManagerFactory().getPersistenceUnitUtil();
Unfortunately, I'm not aware if this will prevent the entity loading from occuring. However, just accessing the otherEntities collection or even obtaining references to each entity will not make the instance to be loaded; you need to invoke a method on the fetched entity in order to be sure it will be loaded.
You also might consider creating a #NamedQuery and return only the OtherEntity ID's.
HTH!
From hibernate reference, section 2.2.2.1.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-property
Declare your columns as lazy initialized:
#Basic(fetch = FetchType.LAZY)
private String getYourProperty() {
}
You also need to disable proxies for your entity class and byte instrument it. There is an example here:
Making a OneToOne-relation lazy
You can use the below HQL as told in the documentation to establish this.
session.createQuery(select new OtherEntity(oe.id) OtherEntity oe
where oe.parentSomeEntity.someId = :someId).list();//also set someId.
Add a constructor in OtherEntity to set the id also there should be a mapping to SomeEntity in OtherEntity.
This HQL will give you a List<OtherEntity> with only id set in the bean.

Categories

Resources