<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<!-- 
    This mapping demonstrates the use of Hibernate with all-handwritten SQL!

    This version is for MySQL
-->

<hibernate-mapping package="org.hibernate.test.sql.hand" default-access="field">

	<class name="Organization">
		<id name="id" unsaved-value="0" column="orgid">
			<generator class="increment"/>
		</id>
		<property name="name" not-null="true"/>
		<set name="employments" 
			inverse="true"
			order-by="DUMMY">
			<key column="employer"/> <!-- only needed for DDL generation -->
			<one-to-many class="Employment"/>
			<loader query-ref="organizationEmployments"/>
		</set>
		<!-- query-list name="currentEmployments" 
			query-ref="organizationCurrentEmployments"-->
		<loader query-ref="organization"/>
		<sql-insert>INSERT INTO Organization (NAME, ORGID) VALUES ( UPPER(?), ? )</sql-insert>
		<sql-update>UPDATE Organization SET NAME=UPPER(?) WHERE ORGID=?</sql-update>
		<sql-delete>DELETE FROM Organization WHERE ORGID=?</sql-delete>
	</class>
	
	<class name="Person">
		<id name="id" unsaved-value="0" column="perid">
			<generator class="increment"/>
		</id>
		<property name="name" not-null="true"/>
		<loader query-ref="person"/>
		<sql-insert>INSERT INTO Person (NAME, PERID) VALUES ( UPPER(?), ? )</sql-insert>
		<sql-update>UPDATE Person SET NAME=UPPER(?) WHERE PERID=?</sql-update>
		<sql-delete>DELETE FROM Person WHERE PERID=?</sql-delete>
	</class>
	
	<class name="Employment">
		<id name="employmentId" unsaved-value="0" column="empid">
			<generator class="increment"/>
		</id>
		<many-to-one name="employee" not-null="true" update="false"/>
		<many-to-one name="employer" not-null="true" update="false"/>
		<property name="startDate" not-null="true" update="false" insert="false"/>
		<property name="endDate" insert="false"/>
		<property name="regionCode" update="false"/>
	  <property name="salary" type="org.hibernate.test.sql.hand.MonetaryAmountUserType">
			<column name="VALUE" sql-type="float"/>
			<column name="CURRENCY"/>			
		</property>
		<loader query-ref="employment"/>
   		<sql-insert>
			INSERT INTO Employment 
				(EMPLOYEE, EMPLOYER, STARTDATE, REGIONCODE, VALUE, CURRENCY, EMPID) 
				VALUES (?, ?, now(), UPPER(?), ?, ?, ?)
		</sql-insert>
		<sql-update>UPDATE Employment SET ENDDATE=?, VALUE=?, CURRENCY=? WHERE EMPID=?</sql-update> 
		<sql-delete>DELETE FROM Employment WHERE EMPID=?</sql-delete> 
	</class>

    <class name="TextHolder">
        <id name="id" column="id">
            <generator class="increment"/>
        </id>
        <property name="description" type="text" length="15000"/>
        <loader query-ref="textholder"/>
        <sql-insert>
            INSERT INTO TextHolder
            (DESCRIPTION, ID)
            VALUES (?, ?)
        </sql-insert>
        <sql-update>UPDATE TextHolder SET DESCRIPTION=? WHERE ID=?</sql-update>
        <sql-delete>DELETE FROM TextHolder WHERE ID=?</sql-delete>
    </class>

    <class name="ImageHolder">
        <id name="id" column="id">
            <generator class="increment"/>
        </id>
        <property name="photo" type="image" length="15000"/>
        <loader query-ref="imageholder"/>
        <sql-insert>
            INSERT INTO ImageHolder
            (PHOTO, ID)
            VALUES (?, ?)
        </sql-insert>
        <sql-update>UPDATE ImageHolder SET PHOTO=? WHERE ID=?</sql-update>
        <sql-delete>DELETE FROM ImageHolder WHERE ID=?</sql-delete>
    </class>
    
    <resultset name="org-emp-regionCode">
        <return-scalar column="regionCode" type="string"/>
        <return alias="org" class="Organization"/>
        <return-join alias="emp" property="org.employments"/>
    </resultset>

    <resultset name="org-emp-person">
        <return alias="org" class="Organization"/>
        <return-join alias="emp" property="org.employments"/>
        <return-join alias="pers" property="emp.employee"/>
    </resultset>
	
	<sql-query name="person">
		<return alias="p" class="Person" lock-mode="upgrade"/>
		SELECT NAME AS {p.name}, PERID AS {p.id} FROM Person WHERE PERID=? /*FOR UPDATE*/
	</sql-query>

	<sql-query name="organization">
		<return alias="org" class="Organization"/>
		<return-join alias="emp" property="org.employments"/>
		SELECT {org.*}, {emp.*}
		FROM Organization org
			LEFT OUTER JOIN Employment emp ON org.ORGID = emp.EMPLOYER
		WHERE org.ORGID=?
	</sql-query>



	<!--sql-query name="organization">
		<return alias="org" class="Organization"/>
		SELECT NAME AS {org.name}, ORGID AS {org.id} FROM ORGANIZATION
		WHERE ORGID=?
	</sql-query-->
	
	<sql-query name="allOrganizationsWithEmployees" flush-mode="never">
		<return alias="org" class="Organization"/>
		SELECT DISTINCT org.NAME AS {org.name}, org.ORGID AS {org.id} 
		FROM Organization org
		INNER JOIN Employment e ON e.EMPLOYER = org.ORGID
	</sql-query>
	
	<sql-query name="employment">
		<return alias="emp" class="Employment"/>
		SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer}, 
			STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
			REGIONCODE as {emp.regionCode}, EMPID AS {emp.id}
		FROM Employment
		WHERE EMPID = ?
	</sql-query>

	
	<sql-query name="organizationEmployments">
		<load-collection alias="empcol" role="Organization.employments"/>
		SELECT {empcol.*}
		FROM Employment empcol
		WHERE EMPLOYER = :id
		ORDER BY STARTDATE ASC, EMPLOYEE ASC
	</sql-query>


	<sql-query name="organizationCurrentEmployments">
		<return alias="emp" class="Employment">		    
			<return-property name="salary"> 
		      <!-- as multi column properties are not supported via the
		      {}-syntax, we need to provide an explicit column list for salary via <return-property> -->
  			  <return-column name="VALUE"/>
			  <return-column name="CURRENCY"/>			
			</return-property>
			<!-- Here we are remapping endDate. Notice that we can still use {emp.endDate} in the SQL. -->
			<return-property name="endDate" column="myEndDate"/>
		</return>
		<synchronize table="EMPLOYMENT"/>
		SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer}, 
			STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
			REGIONCODE as {emp.regionCode}, EMPID AS {emp.id}, VALUE, CURRENCY
		FROM Employment
		WHERE EMPLOYER = :id AND ENDDATE IS NULL
		ORDER BY STARTDATE ASC
	</sql-query>

	<sql-query name="simpleScalar" callable="true">
	 <return-scalar column="name" type="string"/>
	 <return-scalar column="value" type="long"/>
		{ call simpleScalar(:number) }
	</sql-query>

	<sql-query name="paramhandling" callable="true">
		<return-scalar column="value" type="long"/>
		<return-scalar column="value2" type="long"/>
		{ call paramHandling(?,?) }
	</sql-query>

	<sql-query name="paramhandling_mixed" callable="true">
		<return-scalar column="value" type="long" />
		<return-scalar column="value2" type="long" />
		{ call paramHandling(?,:second) }
	</sql-query>
	
	<sql-query name="selectAllEmployments" callable="true">
		<return alias="" class="Employment">
			<return-property name="employee" column="EMPLOYEE"/>
			<return-property name="employer" column="EMPLOYER"/>			
			<return-property name="startDate" column="STARTDATE"/>
			<return-property name="endDate" column="ENDDATE"/>			
			<return-property name="regionCode" column="REGIONCODE"/>			
			<return-property name="id" column="EMPID"/>						
			<return-property name="salary"> 
				<!-- as multi column properties are not supported via the
				{}-syntax, we need to provide an explicit column list for salary via <return-property> -->
				<return-column name="VALUE"/>
				<return-column name="CURRENCY"/>			
			</return-property>
		</return>
		{ call selectAllEmployments() }
	</sql-query>

    <sql-query name="textholder">
        <return alias="h" class="TextHolder" lock-mode="upgrade"/>
        SELECT ID AS {h.id}, DESCRIPTION AS {h.description} FROM TextHolder WHERE ID=? /*FOR UPDATE*/
    </sql-query>

    <sql-query name="imageholder">
        <return alias="h" class="ImageHolder" lock-mode="upgrade"/>
        SELECT ID AS {h.id}, PHOTO AS {h.photo} FROM ImageHolder WHERE ID=? /*FOR UPDATE*/
    </sql-query>

	<database-object>
		<create>
		CREATE PROCEDURE selectAllEmployments ()
			SELECT EMPLOYEE, EMPLOYER, STARTDATE, ENDDATE, 
			REGIONCODE, EMPID, VALUE, CURRENCY
			FROM Employment
		</create>
		<drop>
		DROP PROCEDURE selectAllEmployments
		</drop>
	</database-object>
	
	<database-object>
		<create>
		CREATE PROCEDURE paramHandling (j int, i int) 
			SELECT j AS value, i AS value2
		</create>
		<drop>
		DROP PROCEDURE paramHandling
		</drop>
	</database-object>
	
	<database-object>
		<create>
		CREATE PROCEDURE simpleScalar (number int) 
			SELECT number AS value, 'getAll' AS name
		</create>
		<drop>
		DROP PROCEDURE simpleScalar
		</drop>
	</database-object>
	
</hibernate-mapping>
