Data Modeling in SAP Commerce(Hybris)
Data models in SAP Commerce are defined via items.xml file in each extension. The core-items.xml contains the basic data models and relations which are used like users,products,orders etc.
At build time and database-initialization time, the platform combines all the XML declarations from the extensions being used, and generates Java classes and a database schema.
If your new extension needs new item types, extending existing item types, modifying relationships or adding relationships to the overall data model, you should do it in <custom-extension>-items.xml, located in its own top-level resource directory.
Hybris Type system is used to design data modeling in Hybris. It has the following types supported for data modeling :
- Item types − used to create tables.
- Relation types − used to create relation between tables.
- Atomic types − used to create various Atomic types.
- Collection types − used to create Collections.
- Map Types − used to define maps.
- Enum types − used to define Enums.
Note: The order in which the types are declared in items.xml is very important. The order in which types are defined must conform to below Atomic types, Collection types, Enum types, Map types, Relation types, Item type
Let’s talk more about each type
Item Types
Item types are basic ones which are used to create new tables or to extend existing tables like products/customers to add our own attribute. GenericItem is the default parent of each item type.
<itemtype code="Customer"
extends="User"
jaloclass="de.hybris.platform.jalo.user.Customer"
autocreate="true"
generate="true">
<attributes>
<!-- auto ID which is generated by NumberSeries -->
<attribute autocreate="true" qualifier="customerID" type="java.lang.String">
<modifiers read="true" write="true" search="true" optional="true"/>
<persistence type="property"/>
</attribute>
</attributes>
</itemtype>
You can define new item types in three ways:
1) Define the new item type without extending any existing item type
<itemtype code="PickupPlant" autocreate="true" generate="true" jaloclass="com.custom.core.jalo.PickupPlant">
<description>Pickup Plants</description>
<deployment table="PickupPlant" typecode="30044" />
<attributes>
<attribute qualifier="name" type="localized:java.lang.String" >
<description>Split order name.</description>
<persistence type="property" />
<modifiers read="true" write="true" />
</attribute>
<attribute qualifier="plantId" type="localized:java.lang.String" >
<description>Plant SAP Code</description>
<persistence type="property" />
<modifiers read="true" write="true" />
</attribute>
</attributes>
</itemtype>
We set:
- generate=true — this way Java class files will be generated for this type. Setting the generate modifier to false results in no Java class file being generated for this type. We should set it to true for the first definition of item type.
- autocreate=true — indicates that PickupPlant is a new type and new database entry for this type will be created. We should set it to true for the first definition of item type.
What is deployment table?
Items within SAP Commerce are made persistent by writing values into a database. Within the database, the values are stored in tables. SAP Commerce allows you to explicitly define the database tables where the values of instances of a given type will be written. This process is referred to as deployment.
- deplyoment table modifier: is to pecifies the table where the instances of the item type are stored.
- typecode modifier: is used internally to create item PKs. Using typcode which already exists will cause failure. Typecode values between 0 and 10000 are reserved for hybris internal use, typecode values greater than 10000 can be used — between 0 & 32767.
What is attribute?
While defining the various properties for an item type, we need to define many things about the property itself. We need a data structure for the properties. In Hybris the properties of an item type are known as attributes. The attribute itself could be of primitive type (like string, or integer) or it could be of type like that of any other item type
It corresponds to column of database.
Modifiers for attributes
- read = true — means attribute is readable and getter method will be generated for the attribute. If false, we cannot access it from our java program;
- write=true — means attribute is writable and setter method will be generated for the attribute. If false, we cannot modify the value;
- optional=true — if false, it is mandatory to initialize this attribute. To make attribute not mandatory make it true;
- search — if true, the attribute is searchable through FlexibleSearch queries;
- unique– if true, the attribute must hold a unique value. Similar to unique constraints in DBMS.
Persistent type for attributes
Persistence is one of the property of item type attribute. It can be set to dynamic or property.
If it is set as property, it means that the value will be stored in DB and it’s called persistent attribute.
If it is set as dynamic, it means that the value will not be part of database table. It is just calculated at run time. It’s called dynamic attribute.
2) Define the new item type by extending it with existing item type
<itemtype code="SubCart" extends="Cart" jaloclass="com.custom.core.jalo.order.CchSubCart">
<attributes>
<attribute qualifier="cartId" type="java.lang.String">
<persistence type="property"/>
<modifiers read="true" write="true" optional="false"/>
</attribute>
</attributes>
</itemtype>
We use extends modifier to specifiy parent class, autocreate and generate set as true as it’s a new item type.
3) Define the existing item type again with new attributes
<itemtype code="BaseStore" autocreate="false" generate="false">
<description>Extending BaseStore for usecases</description>
<attributes>
<attribute qualifier="showCreditInformation" type="boolean">
<description>Show or hide user creditinformation</description>
<persistence type="property" />
<defaultvalue>true</defaultvalue>
</attribute>
</attributes></itemtype>
Autocreate and generate are set as false as it’s not new item type. This way we add new attribute to extisting item type without defining new item type.
Atomic Types
These are defined as basic types in Hybris, which include Java number and string objects –java.lang.integer, java.lang.boolean, java.lang.string, java.lang.float, lava.lang.double.
In items.xml:
<atomictypes>
<atomictype class="java.lang.Object" autocreate="true" generate="false"/>
<atomictype class="java.lang.Number" extends="java.lang.Object" autocreate="true" generate="false"/>
<atomictype class="java.lang.Integer" extends="java.lang.Number" autocreate="true" generate="false"/>
<atomictype class="java.lang.Boolean" extends="java.lang.Object" autocreate="true" generate="false"/>
<atomictype class="java.lang.Byte" extends="java.lang.Number" autocreate="true" generate="false"/>
<atomictype class="java.lang.Double" extends="java.lang.Number" autocreate="true" generate="false"/>
<atomictype class="java.lang.Float" extends="java.lang.Number" autocreate="true" generate="false"/>
...........</atomictypes>
Collection Types
Used for creating collections of similar item types.
<collectiontypes>
<collectiontype code="ExampleCollection" elementtype="Item" autocreate="true" generate="false"/>
<collectiontype code="ItemCollection" elementtype="Item" autocreate="true" generate="false"/>
<collectiontype code="StringCollection" elementtype="java.lang.String" autocreate="true" generate="false"/>
<collectiontype code="ObjectCollection" elementtype="java.lang.Object" autocreate="true" generate="false"/>
<collectiontype code="MediaCollection" elementtype="Media" autocreate="true" generate="true"/>
<collectiontype code="AbstractOrderEntryList" elementtype="AbstractOrderEntry" autocreate="true"
generate="false"
type="list"/>
<collectiontype code="CartEntryCollection" elementtype="CartEntry" autocreate="true" generate="false"
type="list"/>
<collectiontype code="OrderEntryCollection" elementtype="OrderEntry" autocreate="true" generate="false"
type="list"/>
<collectiontype code="QuoteEntryCollection" elementtype="QuoteEntry" autocreate="true" generate="false"
type="list"/> <collectiontype code="RegionCollection" elementtype="Region" autocreate="true" generate="false"/>
<collectiontype code="LanguageCollection" elementtype="Language" autocreate="true" generate="true"/>
<collectiontype code="LanguageList" elementtype="Language" autocreate="true" generate="true" type="list"/>
<collectiontype code="LanguageSet" elementtype="Language" autocreate="true" generate="true" type="set"/> <collectiontype code="ViewAttributeList" elementtype="ViewAttributeDescriptor" autocreate="true"
generate="false"
type="list"/>
<collectiontype code="ViewAttributeSet" elementtype="ViewAttributeDescriptor" autocreate="true" generate="false"
type="set"/>
<collectiontype code="configAttributeSet" elementtype="ConfigAttributeDescriptor" autocreate="true"
generate="false"/>
<collectiontype code="subTypesSet" elementtype="ComposedType" autocreate="true" generate="false"/>
<collectiontype code="AtomicTypeSubtypeCollection" elementtype="AtomicType" autocreate="true" generate="false"/>
<collectiontype code="RestrictionList" elementtype="SearchRestriction" autocreate="true" generate="false"/>
...................
</collectiontypes>
Map Types
Map types are used to store key values pairs in SAP Commerce(Hybris).
<maptypes>
<maptype code="ExampleMap"
argumenttype="Language"
returntype="java.math.BigInteger"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.String"
argumenttype="Language"
returntype="java.lang.String"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Integer"
argumenttype="Language"
returntype="java.lang.Integer"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Boolean"
argumenttype="Language"
returntype="java.lang.Boolean"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Double"
argumenttype="Language"
returntype="java.lang.Double"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Float"
argumenttype="Language"
returntype="java.lang.Float"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Long"
argumenttype="Language"
returntype="java.lang.Long"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Short"
argumenttype="Language"
returntype="java.lang.Short"
autocreate="true"
generate="false"/>
<maptype code="localized:java.lang.Character"
argumenttype="Language"
returntype="java.lang.Character"
autocreate="true"
generate="false"/>
<maptype code="localized:java.util.Date"
argumenttype="Language"
returntype="java.util.Date"
autocreate="true"
generate="false"/>
.........</maptypes>
Enum Types
Used to build enumeration in Java for preparing a particular set of values.
<enumtypes>
<enumtype code="TestEnum">
<value code="testValue1"/>
<value code="testValue2"/>
<value code="testValue3"/>
<value code="testValue4"/>
</enumtype>
<enumtype code="EncodingEnum" autocreate="true" generate="true" dynamic="true"/>
<!-- order -->
<enumtype code="CreditCardType" autocreate="true" generate="true">
<value code="amex"/>
<value code="visa"/>
<value code="master"/>
<value code ="diners"/>
</enumtype> <enumtype code="RelationEndCardinalityEnum" autocreate="true" generate="true">
<value code="one"/>
<value code="many"/>
</enumtype>
<enumtype code="MediaManagementTypeEnum" autocreate="true" generate="true">
<value code="FILES"/>
<value code="SSH"/>
<value code="FTP"/>
</enumtype>
<!-- hmc legacy - Saved Values -->
<enumtype code="SavedValueEntryType" autocreate="true" generate="true">
<value code="created"/>
<value code="removed"/>
<value code="changed"/>
</enumtype>
<enumtype code="PhoneContactInfoType" generate="true" autocreate="true" dynamic="true">
<description>Phone type</description>
<value code="MOBILE"/>
<value code="WORK"/>
<value code="HOME"/>
</enumtype>
<!-- quote -->
<enumtype code="QuoteState" autocreate="true" generate="true" dynamic="true">
<value code="CREATED"/>
<value code ="DRAFT"/>
<value code="SUBMITTED"/>
<value code="OFFER"/>
<value code="ORDERED"/>
<value code="CANCELLED"/>
<value code="EXPIRED"/>
</enumtype>............
</enumtypes>
Relation Types
These are used for defining relations between two tables in SAP Commerce(Hybris).
<relations> <relation code="PrincipalGroupRelation" autocreate="true" generate="false" localized="false"
deployment="de.hybris.platform.persistence.link.PrincipalGroupRelation">
<sourceElement qualifier="members" type="Principal" collectiontype="set" cardinality="many" ordered="false">
<modifiers read="true" write="true" search="true" optional="true"/>
</sourceElement>
<targetElement qualifier="groups" type="PrincipalGroup" collectiontype="set" cardinality="many"
ordered="false">
<modifiers read="true" write="true" search="true" optional="true"/>
</targetElement>
</relation>
<!-- MediaContainer stuff PLA-5950 -->
<relation code="MediaContainer2MediaRel" localized="false" generate="true" autocreate="true">
<sourceElement type="MediaContainer" qualifier="mediaContainer" cardinality="one">
<modifiers read="true" write="true" search="true" optional="true"/>
</sourceElement>
<targetElement type="Media" qualifier="medias" cardinality="many">
<modifiers read="true" write="true" search="true" optional="true"/>
</targetElement>
</relation>
<relation code="MediaContext2MediaFormatMappingRel" localized="false" generate="true" autocreate="true">
<sourceElement type="MediaContext" qualifier="mediaContext" cardinality="one">
<modifiers read="true" write="true" search="true" optional="false" unique="true"/>
</sourceElement>
<targetElement type="MediaFormatMapping" qualifier="mappings" cardinality="many">
<modifiers read="true" write="true" search="true" optional="true" partof="true"/>
</targetElement>
</relation>
<relation code="Media2DerivedMediaRel" localized="false" generate="true" autocreate="true">
<sourceElement type="Media" qualifier="media" cardinality="one">
<modifiers read="true" write="true" search="true" optional="false"/>
</sourceElement>
<targetElement type="DerivedMedia" qualifier="derivedMedias" cardinality="many">
<modifiers read="true" write="true" search="true" optional="true" partof="true"/>
</targetElement>
</relation>
<relation code="User2Orders" generate="true" localized="false" autocreate="true">
<sourceElement type="User" cardinality="one" qualifier="user">
<modifiers read="true" write="true" search="true" optional="false"/>
</sourceElement>
<targetElement type="Order" cardinality="many" qualifier="orders">
<modifiers read="true" write="true" search="true" optional="true" partof="true"/>
</targetElement>
</relation> </relations>
Sources:
https://www.tutorialspoint.com/sap_hybris/sap_hybris_modelling.html
https://www.tutorialspoint.com/sap_hybris/sap_hybris_modelling.html
Make sure you give this post a clap and follow my blog if you find it helpful.