I have an entity defined in my XML persistence file as shown below. The entity/table in question has over 100 fields, but I only need a handful. Rather than marking all the fields I don't need with a fetch="LAZY" attribute, can I make the default fetch strategy for all columns for this table be LAZY and only mark the ones I need as fetch="EAGER" ?
I looked thru the Open JPA documentation here, but I did not see any reference to this. Is this possible in the XML entity-mappings?
<entity class="Users">
<table schema="dbo" name="Users"/>
<attributes>
<id name="id">
<column name="Id" column-definition="nchar" length="18"/>
</id>
<basic name="about" fetch="LAZY">
<column name="About" column-definition="nvarchar" length="1000"/>
</basic>
<basic name="accountId">
<column name="AccountId" column-definition="nchar" length="18"/>
</basic>
<basic name="alias">
<column name="Alias" column-definition="nvarchar" nullable="false" length="8"/>
</basic>
<basic name="auditCounter">
<column name="AuditCounter"/>
</basic>
<basic name="auditPercent">
<column name="AuditPercentc"/>
</basic>
<basic name="auditTarget">
<column name="Audit"/>
</basic>
<basic name="CenterId">
<column name="CenterId" column-definition="nchar" length="18"/>
</basic>
</attributes>
</entity>
It seems an entity graph is what you're after.
https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs001.htm
What the above link implies is that you could mark the fields you need to be fetched eagerly, then use an empty load graph with your queries.
Or, you could use a fetch graph, explicitly listing the properties you're interested in, to control the fetch mode on a per-query basis.
The confusing part about the entity graph specification is that basic fields need to be explicitly marked as eagerly fetched as well, despite that (as far as annotation-based configuration goes, at least), the default value for Basic.fetch property is already FetchMode.EAGER. I have no idea what the behavior will be with XML-based configuration, so I suggest you go with the fetch graph approach and make sure it actually works.
Related
I am trying to create Relationship between 3 tables. Following are the tables:
rooms
facilities
facilityMapping
rooms table contains
roomId
roomName
facilities table contains
facilityId
facilityName
facilityMapping table contains
facilityId
roomId
facilityQuantity
In facilityMapping table I want to create Reference to above two tables.
In service.xml I am trying to create Reference
<service-builder package-path="com.admin.services">
<namespace>rbms</namespace>
<entity name="rooms" local-service="true" remote-service="false">
<column name="roomId" type="int" primary="true"></column>
<column name="roomName" type="String"></column>
<column name="roomFloorNo" type="int"></column>
<column name="roomLocationName" type="String"></column>
<column name="roomCapacity" type="int"></column>
<column name="roomImages" type="String"></column>
</entity>
<entity name="facilities" local-service="true" remote-service="false">
<column name="facilityId" type="int" primary="true"></column>
<column name="facilityName" type="String"></column>
<!--
|- Finding Equipments using their Names and display it in form
|- It will help you to add new Room.
-->
<finder name="facilityName" return-type="Collection">
<finder-column name="facilityName"></finder-column>
</finder>
</entity>
<entity name="facilityMapping" remote-service="false" local-service="true">
<column name="facilityId" type="int"></column>
<column name="roomId" type="int"></column>
<column name="facilityQuantity" type="int"></column>
<column name="fk_fid" type="Collection" entity="com.admin.services.facilities" mapping-key="facilityId"></column>
</entity>
</service-builder>
Error : mapping-key must be declared for element-type column
As mapping-key is deprecated in new Liferay Version I am getting my work done using mapping-table attribute
I wanna set lazy to "false" but only to one method at in runtime.
Can I do?
this.getSession().createSQLQuery("select * from customers....")....
Attention: im using createSQLQuery not createCriteria.
CustomerMapping.xml here:
<hibernate-mapping>
<class name="com.example.entities.customers.Customer"
table="CUSTOMERS">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence">
<param name="sequence">seq_customers</param>
</generator>
</id>
<property name="name" type="String">
<column name="NAME_C" />
</property>
<many-to-one name="address"
class="com.example.entities.Address" fetch="select"
cascade="all">
<column name="ADDRESS_ID" />
</many-to-one>
</class>
</hibernate-mapping>
I wanna set lazy to false for Address.
I have to do this because this method return a list of customers (with address) and when I iterate this list and print its very slow cause the lazy is setted true (by default).
Is there a reason you are using SQL instead of HQL? I would stay away from SQL statements when using hibernate when possible.
I would implement it like this in HQL:
from Customer c
join fetch c.address
the join fetch makes Customers address no longer lazy.
I have a mapping file which sets lazy=false for some related entities. This makes sense for a lot of use cases but there are some exceptions. The problem is that I dont want to fetch the related associations at query time for these cases, which are very expensive time-wise.
Example of the mapping for the entity.
<class name="Category" table="category">
<id name="id" type="string">
<column length="50" name="id"/>
<generator class="uuid"/>
</id>
<property name="name" type="string">
<column length="100" name="name" not-null="true"/>
</property>
<set inverse="true" lazy="false" name="categorySourcesList">
<key>
<column length="50" name="categoryid" not-null="true"/>
</key>
<one-to-many class="CategorySource"/>
</set>
</class>
My question is, is there a way to override the lazy value which is set in the mapping file, either in the sql-query I custom write or enabling lazy load as one of the parameters in the DAO? or through some annotations?
Yes, you can override the annotated or xml mapped association fetching strategy.
Hibernate Documentation
Criteria criteria = session().createCriteria(MyClass.class);
criteria.add(Restrictions.eq("id", "1234"));
criteria.setFetchMode("children",FetchMode.EAGER);
return (MyClass) criteria.uniqueResult();
This will return you an instance of MyClass with its children eagerly fetched.
AFAIK you can't override EAGER loading with LAZY but only the other way round.
Thus, you'd need to define the association the be LAZY and override that in the queries using joins. There might be other ways to do that but I'm afraid that's all I know right now.
I want to override column names in by subclass using xml.
i know this can be done using #AttributeOverride JPA Anotations but want to achieve the same using XML Configuration ?
You can use the embedded and attribute-override elements.
See Chapter 3. Overriding metadata through XML/3.1.3. Property level metadata.
An example from this document:
<attributes>
<id name="id">
<column name="fld_id"/>
<generated-value generator="generator" strategy="SEQUENCE"/>
<temporal>DATE</temporal>
<sequence-generator name="generator" sequence-name="seq"/>
</id>
<version name="version"/>
<embedded name="embeddedObject">
<attribute-override name"subproperty">
<column name="my_column"/>
</attribute-override>
</embedded>
<basic name="status" optional="false">
<enumerated>STRING</enumerated>
</basic>
<basic name="serial" optional="true">
<column name="serialbytes"/>
<lob/>
</basic>
<basic name="terminusTime" fetch="LAZY">
<temporal>TIMESTAMP</temporal>
</basic>
</attributes>
I am using Hibernate. My database is as follows
A Category has many attributes
class category
contains
private Set <Attribute> AllAttributes= new HashSet <Attribute>();
class attribute
How do I retrieve all categories together with their attributes because I am trying 'from category' but it is not working
Category Mapping File:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 16, 2010 8:37:02 AM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
<class name="com.BiddingSystem.Models.Category" table="CATEGORY">
<id name="CategoryId" type="long">
<column name="CATEGORYID" />
<generator class="native" />
</id>
<property name="CategoryName" type="java.lang.String">
<column name="CATEGORYNAME" />
</property>
<many-to-one name="ParentCategory" class="com.BiddingSystem.Models.Category">
<column name="PARENT_CATEGORY_ID" />
</many-to-one>
<set name="SubCategory" lazy="false" cascade="all-delete-orphan" inverse="true">
<key>
<column name="PARENT_CATEGORY_ID" />
</key>
<one-to-many class="com.BiddingSystem.Models.Category" />
</set>
<set name="AllAttributes" table="ATTRIBUTE" inverse="false" lazy="true" cascade="all">
<key>
<column name="CATEGORYID" />
</key>
<one-to-many class="com.BiddingSystem.Models.Attribute" />
</set>
</class>
</hibernate-mapping>
Attribute Mapping File:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 16, 2010 5:25:09 AM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
<class name="com.BiddingSystem.Models.Attribute" table="ATTRIBUTE">
<id name="AttributeId" type="long">
<column name="ATTRIBUTEID" />
<generator class="native" />
</id>
<property name="AttributeName" type="java.lang.String">
<column name="ATTRIBUTENAME" />
</property>
<set name="Options" table="ATTRIBUTEOPTION" inverse="false" cascade="all">
<key>
<column name="ATTRIBUTEID" />
</key>
<one-to-many class="com.BiddingSystem.Models.AttributeOption" />
</set>
</class>
</hibernate-mapping>
You have mapped the association with lazy="true". This tells hibernate that by default, a category's attributes should only be loaded from the database when they are actually accessed, in contrast to lazy="false" which would instruct hibernate to load the attributes whenever it loads a category. However, the directive in the mapping file affects all queries.
In case you want it only for a particular query, check out
http://docs.jboss.org/hibernate/core/3.5/reference/en/html/queryhql.html#queryhql-joins :
A "fetch" join allows associations or
collections of values to be
initialized along with their parent
objects using a single select. This is
particularly useful in the case of a
collection. It effectively overrides
the outer join and lazy declarations
of the mapping file for associations
and collections. See Section 20.1,
“Fetching strategies” for more
information.
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
A fetch join does not usually need to
assign an alias, because the
associated objects should not be used
in the where clause (or any other
clause). The associated objects are
also not returned directly in the
query results. Instead, they may be
accessed via the parent object. The
only reason you might need an alias is
if you are recursively join fetching a
further collection:
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens child
left join fetch child.kittens
The fetch construct cannot be used in
queries called using iterate() (though
scroll() can be used). Fetch should be
used together with setMaxResults() or
setFirstResult(), as these operations
are based on the result rows which
usually contain duplicates for eager
collection fetching, hence, the number
of rows is not what you would expect.
Fetch should also not be used together
with impromptu with condition. It is
possible to create a cartesian product
by join fetching more than one
collection in a query, so take care in
this case. Join fetching multiple
collection roles can produce
unexpected results for bag mappings,
so user discretion is advised when
formulating queries in this case.
Finally, note that full join fetch and
right join fetch are not meaningful.