{"id":4,"date":"2011-09-08T07:46:03","date_gmt":"2011-09-08T12:46:03","guid":{"rendered":"http:\/\/www.alphastar.net.au\/wordpress\/?p=4"},"modified":"2011-09-27T13:34:55","modified_gmt":"2011-09-27T03:34:55","slug":"delving-into-hibernate","status":"publish","type":"post","link":"https:\/\/alphastar.net.au\/weblog\/2011\/09\/08\/delving-into-hibernate\/","title":{"rendered":"Diving into Hibernate"},"content":{"rendered":"<p>I&#8217;ve written this Hibernate tutorial to learn how various mappings work in Hibernate and maybe help out other new-comers in the process. I am going to cover\u00c2\u00a02 mapping cardinalities (1-many, many-many) for entity types and\u00c2\u00a0 a 1-1 mapping for a value type (actually value types are always 1-1)\u00c2\u00a0.<\/p>\n<p><span style=\"text-decoration: underline;\">Software needed<\/span><\/p>\n<ul>\n<li>MySQL<\/li>\n<li>MySQL Workbench<\/li>\n<li>MySQL connector<\/li>\n<li>Hibernate 3.6 or higher (earlier versions should be ok)<\/li>\n<li>Eclipse (any recent verion)<\/li>\n<li>log4j<\/li>\n<\/ul>\n<p><span style=\"text-decoration: underline;\">Directory and project setup<\/span><\/p>\n<p>Create a new project in eclipse (whatever name you like) and add the following jar files to the project<\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/wordpress\/wp-content\/uploads\/2011\/09\/jars1.jpg\"><\/a><a href=\"http:\/\/www.alphastar.net.au\/wordpress\/wp-content\/uploads\/2011\/09\/jars.jpg\"><\/a><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/jars2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-26\" title=\"jars\" src=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/jars2.jpg\" alt=\"\" width=\"587\" height=\"499\" \/><\/a><\/p>\n<p>Create a package for the model (alphastar.model). The POJOs will reside here.<br \/>\nCreate a package for the code (alphastar.main).\u00c2\u00a0\u00c2\u00a0The program logic goes here<\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/projlayout1.jpg\"><\/a><\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/projlayout.jpg\"><\/a><\/p>\n<p>In this small application, I will model a Stock-market portfolio.<\/p>\n<p>The following schema will apply:<\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/wordpress\/wp-content\/uploads\/2011\/09\/Diagram1.jpg\"><\/a><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/Diagram11.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-27\" title=\"Diagram1\" src=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/Diagram11.jpg\" alt=\"\" width=\"541\" height=\"421\" \/><\/a><\/p>\n<p>This diagram specifies that a Person may own 1 or more stock codes (ie. unique stocks) and that each unique stock code may be owned by one or more\u00c2\u00a0Persons (lets consider this possibility even though it may not be 100% real world).\u00c2\u00a0Essentially we are modelling a many-to-many scenario here.<\/p>\n<p>Additionally, each stock code may have a number of stock &#8220;events&#8221; associated to it. By this I mean a buy or sell action performed on a stock. For instance, a buy for stock code ABC, buy\/sell on stock code XYZ. This is modelling a one-to-many scenario. One stock may have a number of purchasing events associated to it.<\/p>\n<p>Address is being modelled as a value type. A value type is always associated to it&#8217;s owning class and does not have an indentity outside of it&#8217;s owning class. In hibermate, value types are coalesced into the table of the owning class (they do not reside in a seperate table ).<\/p>\n<p>Hibernate has the concept of a persistence context. The persistence context knows the state of all objects within the transaction, and can automatically\u00c2\u00a0generate the correct update and insert statements based on the modifications made to objects. Objects that aren&#8217;t known to the persistence manager are known as transient (ie. when you create a new object). Also objects that are modified after a persistence context is closed are known as detached. When objects are in those 2 states, Hibernate does not know about them and there will be no database updates.<\/p>\n<p><!--more--><\/p>\n<p>Back to the application.<\/p>\n<p>First of all we want to create the Hibernate configuration file<\/p>\n<p>[code lang=&#8221;xml&#8221;]<\/p>\n<p>com.mysql.jdbc.Driver   jdbc:mysql:\/\/localhost\/stocks   root   (pass)   org.hibernate.dialect.HSQLDialect  1 org.hibernate.dialect.MySQLDialect thread org.hibernate.cache.NoCacheProvider true update true true<\/p>\n<p>[\/code]<\/p>\n<p>This is a pretty standard config file. The POJO classes that we have annotated are included in the mapping tag.<\/p>\n<p>Next we want to create a helper class that calls the Hibernate sessionFactory. This will instansiate a Hibernate session for us. Note that only one session from the factory is ever instansiated.<br \/>\nCreate a file called HibernateUtil.java and place it in the alphatar.main package\/directory.<\/p>\n<p>[code lang=&#8221;java&#8221;]<\/p>\n<p>package alphastar.main;<\/p>\n<p>import org.hibernate.SessionFactory;<br \/>\nimport org.hibernate.cfg.Configuration;<\/p>\n<p>public class HibernateUtil {<br \/>\nprivate static final SessionFactory sessionFactory = buildSessionFactory();<br \/>\nprivate static SessionFactory buildSessionFactory() {<br \/>\ntry {<br \/>\nreturn new Configuration().configure().buildSessionFactory();<br \/>\n}<br \/>\ncatch (Throwable e) {<br \/>\nSystem.out.println(&#8220;Error:&#8221; + e);<br \/>\nthrow new ExceptionInInitializerError(e);<br \/>\n}<br \/>\n}<br \/>\npublic static SessionFactory getSessionFactory() {<br \/>\nreturn sessionFactory;<br \/>\n}<br \/>\n}<\/p>\n<p>[\/code]<\/p>\n<p><strong>POJO&#8217;s<\/strong><\/p>\n<p>There are a number of POJOs (Plain old Java Objects) that store data from the database.<\/p>\n<p><span style=\"text-decoration: underline;\">Person<\/span><\/p>\n<p>[code lang=&#8221;Java&#8221;]<br \/>\npackage alphastar.model;<\/p>\n<p>import java.util.HashSet;<br \/>\nimport java.util.Set;<\/p>\n<p>import javax.persistence.*;<\/p>\n<p>@Entity<br \/>\n@Table (name=&#8221;Person&#8221;)<br \/>\npublic class Person {<\/p>\n<p>int personId;<br \/>\nprivate String name;<br \/>\nAddress address;<\/p>\n<p>private Set stocksHeld = new HashSet();<\/p>\n<p>@Id<br \/>\n@GeneratedValue(strategy = GenerationType.AUTO)<br \/>\n@Column(name = &#8220;idperson&#8221;)<br \/>\npublic int getPersonId() {<br \/>\nreturn personId;<br \/>\n}<br \/>\npublic void setPersonId(int personId) {<br \/>\nthis.personId = personId;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;name&#8221;)<br \/>\npublic String getName() {<br \/>\nreturn name;<br \/>\n}<br \/>\npublic void setName(String name) {<br \/>\nthis.name = name;<br \/>\n}<\/p>\n<p>@Embedded<br \/>\npublic Address getAddress() {<br \/>\nreturn address;<br \/>\n}<br \/>\npublic void setAddress(Address address) {<br \/>\nthis.address = address;<br \/>\n}<\/p>\n<p>@ManyToMany<br \/>\n@JoinTable(<br \/>\nname=&#8221;PersonStockJoinTable&#8221;,<br \/>\njoinColumns = {@JoinColumn(name= &#8220;idperson&#8221;)},<br \/>\ninverseJoinColumns = {@JoinColumn(name = &#8220;idstock&#8221;)}<br \/>\n)<br \/>\n@org.hibernate.annotations.IndexColumn(name = &#8220;DISPLAY_POSITION&#8221;)<br \/>\npublic Set getStocksHeld() {<br \/>\nreturn stocksHeld;<br \/>\n}<br \/>\npublic void setStocksHeld(Set stocksHeld) {<br \/>\nthis.stocksHeld = stocksHeld;<br \/>\n}<\/p>\n<p>\/\/ ASSOCIATION SETTERS<br \/>\npublic void addStock(Stock aStock) {<br \/>\nstocksHeld.add(aStock);<br \/>\n}<br \/>\n}<\/p>\n<p>[\/code]<\/p>\n<p>As this is a many to many association, a 3rd intermediary table is  needed to map foreign keys from either table. I have named this  &#8220;PersonStockJoinTable&#8221;.<\/p>\n<p>Address is an embedded value-type. It is like a 1-1 association,  except that it is completely dependant on the owning object and has no  identity outside of the owning object (ie shared references aren&#8217;t  possible). Also, as the data for Address is so closely associated  with\u00c2\u00a0the Person object, the data for both are stored together in one  table.<\/p>\n<p><span style=\"text-decoration: underline;\">Address<\/span><br \/>\n[code lang=&#8221;Java&#8221;]<br \/>\npackage alphastar.model;<\/p>\n<p>import javax.persistence.Column;<br \/>\nimport javax.persistence.Embeddable;<br \/>\nimport javax.persistence.Table;<\/p>\n<p>@Embeddable<br \/>\n@Table (name=&#8221;address&#8221;)<br \/>\npublic class Address {<\/p>\n<p>private String addressLine1;<br \/>\nprivate String addressLine2;<br \/>\nint postCode;<br \/>\nString city;<\/p>\n<p>@Column(name = &#8220;addressline1&#8221;, nullable=false)<br \/>\npublic String getAddressLine1() {<br \/>\nreturn addressLine1;<br \/>\n}<br \/>\npublic void setAddressLine1(String addressLine1) {<br \/>\nthis.addressLine1 = addressLine1;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;addressline2&#8221;, nullable=true)<br \/>\npublic String getAddressLine2() {<br \/>\nreturn addressLine2;<br \/>\n}<br \/>\npublic void setAddressLine2(String addressLine2) {<br \/>\nthis.addressLine2 = addressLine2;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;zipcode&#8221;, nullable=false)<br \/>\npublic int getPostCode() {<br \/>\nreturn postCode;<br \/>\n}<br \/>\npublic void setPostCode(int postCode) {<br \/>\nthis.postCode = postCode;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;city&#8221;, nullable=false)<br \/>\npublic String getCity() {<br \/>\nreturn city;<br \/>\n}<br \/>\npublic void setCity(String city) {<br \/>\nthis.city = city;<br \/>\n}<\/p>\n<p>}<\/p>\n<p>[\/code]<\/p>\n<p>The Address value type, set as an embeddable object within Person<\/p>\n<p><span style=\"text-decoration: underline;\">Stock<\/span><br \/>\n[code lang=&#8221;Java&#8221;]<br \/>\npackage alphastar.model;<\/p>\n<p>import java.util.HashSet;<br \/>\nimport java.util.Set;<\/p>\n<p>import javax.persistence.*;<\/p>\n<p>@Entity<br \/>\n@Table (name=&#8221;stock&#8221;)<br \/>\n\/\/@org.hibernate.annotations.AccessType(&#8220;field&#8221;)<br \/>\npublic class Stock {<\/p>\n<p>public int idstock;<\/p>\n<p>private Set stockEvents = new HashSet(0);<\/p>\n<p>public String code;<\/p>\n<p>public String name;<\/p>\n<p>public void addStockEvent(StockEvent se) {<br \/>\n\/\/ save associations to both ends<br \/>\nse.setStock(this);<br \/>\nstockEvents.add(se);<br \/>\n}<\/p>\n<p>private Set<br \/>\npersons = new HashSet();<\/p>\n<p>\/\/ ASSOCIATION SETTERS<\/p>\n<p>public void addPerson(Person aPerson) {<br \/>\npersons.add(aPerson);<br \/>\n}<\/p>\n<p>\/\/ GETTERS<\/p>\n<p>@Id<br \/>\n@GeneratedValue(strategy = GenerationType.AUTO)<br \/>\n@Column(name = &#8220;idstock&#8221;)<br \/>\npublic int getIdstock() {<br \/>\nreturn idstock;<br \/>\n}<\/p>\n<p>\/\/ when a parent is saved, so is its children<br \/>\n@OneToMany( cascade={CascadeType.PERSIST, CascadeType.MERGE}, mappedBy=&#8221;stock&#8221;)<br \/>\n@org.hibernate.annotations.Cascade({<br \/>\norg.hibernate.annotations.CascadeType.SAVE_UPDATE<br \/>\n})<br \/>\npublic Set getStockEvents() {<br \/>\nreturn stockEvents;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;code&#8221;)<br \/>\npublic String getCode() {<br \/>\nreturn code;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;name&#8221;)<br \/>\npublic String getName() {<br \/>\nreturn name;<br \/>\n}<\/p>\n<p>@ManyToMany(mappedBy=&#8221;stocksHeld&#8221;)<br \/>\n\/*<br \/>\n@JoinTable(<br \/>\nname=&#8221;PersonStockJoinTable&#8221;,<br \/>\njoinColumns = {@JoinColumn(name= &#8220;idstock&#8221;)},<br \/>\ninverseJoinColumns = {@JoinColumn(name = &#8220;idperson&#8221;)}<br \/>\n)<br \/>\n@org.hibernate.annotations.IndexColumn(name = &#8220;DISPLAY_POSITION&#8221;)<br \/>\n*\/<br \/>\npublic Set<br \/>\ngetPersons() {<br \/>\nreturn persons;<br \/>\n}<\/p>\n<p>\/\/ SETTERS<\/p>\n<p>public void setIdstock(int idstock) {<br \/>\nthis.idstock = idstock;<br \/>\n}<\/p>\n<p>public void setStockEvents(Set stockEvents) {<br \/>\nthis.stockEvents = stockEvents;<br \/>\n}<\/p>\n<p>public void setCode(String code) {<br \/>\nthis.code = code;<br \/>\n}<\/p>\n<p>public void setName(String name) {<br \/>\nthis.name = name;<br \/>\n}<\/p>\n<p>public void setPersons(Set<br \/>\npersons) {<br \/>\nthis.persons = persons;<br \/>\n}<br \/>\n}<\/p>\n<p>[\/code]<\/p>\n<p>One thing to note, is that we use a mappedBy attribute to specify that this is the inverse part of the may-to-many relationship. This is due to an idiosnycracy with the way bi-directional associations work in Hibernate. If there are associations to both classes,\u00c2\u00a0Hibernate will try to add the same key twice in the join table. To counteract this, need to set one side as the inverse of the many-to-many by using mappedBy and specifying the variable. Basically it says these 2 things go\u00c2\u00a0together.<\/p>\n<p>If there was no bi-directional association in the code (i.e. Person referenced Stock only), the commented out code would work fine.<\/p>\n<p><span style=\"text-decoration: underline;\">StockEvent<\/span><br \/>\n[code lang=&#8221;Java&#8221;]<br \/>\npackage alphastar.model;<\/p>\n<p>import java.math.BigDecimal;<br \/>\nimport javax.persistence.*;<\/p>\n<p>@Entity<br \/>\n@Table(name=&#8221;stockevent&#8221;)<br \/>\npublic class StockEvent {<\/p>\n<p>public int idStockEvent;<br \/>\npublic Stock stock;<br \/>\npublic BigDecimal buyPrice;<br \/>\npublic java.util.Date buyDate;<br \/>\npublic BigDecimal soldPrice;<br \/>\npublic java.util.Date soldDate;<\/p>\n<p>@Id<br \/>\n@GeneratedValue(strategy = GenerationType.AUTO)<br \/>\n@Column(name = &#8220;idstockevent&#8221;)<br \/>\npublic int getIdStockEvent() {<br \/>\nreturn idStockEvent;<br \/>\n}<\/p>\n<p>public void setIdStockEvent(int idStockEvent) {<br \/>\nthis.idStockEvent = idStockEvent;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;buyprice&#8221;)<br \/>\npublic BigDecimal getBuyPrice() {<br \/>\nreturn buyPrice;<br \/>\n}<\/p>\n<p>public void setBuyPrice(BigDecimal buyPrice) {<br \/>\nthis.buyPrice = buyPrice;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;buydate&#8221;)<br \/>\npublic java.util.Date getBuyDate() {<br \/>\nreturn buyDate;<br \/>\n}<\/p>\n<p>public void setBuyDate(java.util.Date buyDate) {<br \/>\nthis.buyDate = buyDate;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;soldprice&#8221;)<br \/>\npublic BigDecimal getSoldPrice() {<br \/>\nreturn soldPrice;<br \/>\n}<\/p>\n<p>public void setSoldPrice(BigDecimal soldPrice) {<br \/>\nthis.soldPrice = soldPrice;<br \/>\n}<\/p>\n<p>@Column(name = &#8220;solddate&#8221;)<br \/>\npublic java.util.Date getSoldDate() {<br \/>\nreturn soldDate;<br \/>\n}<\/p>\n<p>public void setSoldDate(java.util.Date soldDate) {<br \/>\nthis.soldDate = soldDate;<br \/>\n}<\/p>\n<p>@ManyToOne (targetEntity = alphastar.model.Stock.class)<br \/>\n@JoinColumn (name=&#8221;idstock&#8221;, nullable=false)<br \/>\npublic Stock getStock() {<br \/>\nreturn stock;<br \/>\n}<br \/>\npublic void setStock(Stock stk) {<br \/>\nstock = stk;<br \/>\n}<br \/>\n}<\/p>\n<p>[\/code]<\/p>\n<p><strong>Database<\/strong><\/p>\n<p>MySQL is the database vendor I am using for this project. Open MySQL Workbench and create a database called &#8220;stocks&#8221; and set it as the default database. Important note: We don&#8217;t need to create the database schema as Hibernate will create it automatically when we run the project! It will also choose the appropriate SQL database types based on the data types in the Java classes, which is very nice!<\/p>\n<p>These tables should have been created after you ran the project<\/p>\n<p><strong>Project Layout<\/strong><\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/projlayout.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-21 alignnone\" title=\"projlayout\" src=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2011\/09\/projlayout.jpg\" alt=\"\" width=\"224\" height=\"254\" \/><\/a><\/p>\n<p><strong><br \/>\n<\/strong><\/p>\n<p><strong>Project download<\/strong><\/p>\n<p>The zip file is <a href=\"http:\/\/alphastar.net.au\/code\/project1.zip\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve written this Hibernate tutorial to learn how various mappings work in Hibernate and maybe help out other new-comers in the process. I am going to cover\u00c2\u00a02 mapping cardinalities (1-many,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-4","post","type-post","status-publish","format-standard","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/4","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/comments?post=4"}],"version-history":[{"count":43,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/4\/revisions"}],"predecessor-version":[{"id":67,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/4\/revisions\/67"}],"wp:attachment":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/media?parent=4"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/categories?post=4"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/tags?post=4"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}