package com.farata.dto2extjs.annotations; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Is used to maintain link between the auto-incremented primaryKey of the parent model and * corresponding foreignKey of the child one. * <p> * <table class="innertable"> * <tr> * <th>Parameter</th><th>Type</th><th>Required</th><th>Description</th> * </tr> * <tr> * <td><code>primaryKey</code></td><td>String</td><td>Optional</td> * <td>The name of the primaryKey property in the parent's class. Default value is <code>id</code>. * </td> * </tr> * <tr> * <td><code>foreignKey</code></td><td>String</td><td>Required</td> * <td>Name of a property in this model that is many-to-one related to the property you annotate * </td> * </tr> * </table> * </p> * <p> * The following snippet illustrates how a <code>departmentId</code> property in <code>EmployeeDTO</code> is many-to-one * mapped to the parent class <code>Department</code>. The primary key (of the parent) is, by default, <code>id</code>: * <pre> * @JSClass * public class EmployeeDTO { * . . . * public String departmentId; * @JSManyToOne(foreignKey = "departmentId") * public DepartmentDTO department; * } * </pre> * </p> * <p> * A transaction inserting records into two PK-FK related tables may need a special treatment when the database autoincrements primary keys. * The problem is that auto-incremented values are available only upon <u>completion</u> of INSERT of the parent. * The very same values take place as foreign keys in the associated child record. And, to * adhere to referential constraints, application * need to properly set them <u>prior</u> to INSERT of the children. * </p> * <p>Clear Data Builder's technique to handle this requirement assumes that:<br> * a) JavaScript code should use * locally unique negative values and assign them to both parent's PK and children FK fields.<br> * b) Java server code has to replace the negative FK values with the real ones available upon inserting the parent records. * </p> * <p> * For instance, if a company department has many employees, and <code>departmentDTO.id</code> is initialized by application to -1, * every one-to-many child <code>employeeDTO</code> should arrive to the server with <code>employeeDTO.departmentId</code> preset to -1 as well. * If there is another new <code>departmentDTO</code> in the same transaction batch it should come with PK=-2, and, it's children with * FK=-2, and so on. * </p> * <p>The following snippet of code illustrates the Java code that adheres to this technique: * <PRE> * // Departments get inserted into the database * public void getDepartments_doCreate(ChangeObject changeObject) { DepartmentDTO dto = (DepartmentDTO) changeObject.getNewVersion(); Object tempId = dto.getId(); departmentMyBatisMapper.create(dto); changeObject.addChangedPropertyName("id"); //PK got autoincremented Object primaryKey = dto.getId(); IdExhange.put("clear.samples.dto.DepartmentDTO", "id", tempId, primaryKey); } ..... // Employees get inserted into the database * public void getEmployees_doCreate(ChangeObject changeObject) { EmployeeDTO dto = (EmployeeDTO) changeObject.getNewVersion(); Object tempId = dto.getId(); Object foreignKey = IdExhange.get("clear.samples.dto.DepartmentDTO", "id"); employeeMyBatisMapper.create(dto); changeObject.addChangedPropertyName("id"); //PK got autoincremented Object primaryKey = dto.getId(); IdExhange.put("clear.samples.dto.EmployeeDTO", "id", tempId,primaryKey); } </p> */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.METHOD, ElementType.FIELD }) public @interface JSManyToOne { public abstract String primaryKey() default "id"; public abstract String foreignKey(); }