ABAP表生成Java实体Bean

项目中需要将HR模块中的表数据同步到Java系统中,向外围系统提供分发与查询服务,涉及到的表有两百多张,字段好几千上万个,如果手工一张张这些ABAP表在Java系统数据库中创建一遍的话,工作量将非常大,而且容易出错。

该ABAP代码就是将需要的表转换成Java中的实体Bean,然后就可以使用Hibernate之类的持久化框架来自动生成表了。

ABAP代码没有重构过,写得有点乱......将就着看吧


REPORT  ytab2javabean.
DATAp_table TYPE string.

START-OF-SELECTION.

DATAlv_path TYPE string.
  lv_path 'D:\test'.
**配置文件:以竖线分隔,第一列:SAP表名(注:SAP表名需全大写),第二列:新建表名,第三列:JavaBean名称,第四列:生成的JavaBean所在包路径
DATAfilename TYPE string VALUE 'TableCFG.txt'.
CONCATENATE lv_path `\` filename INTO filename.

TYPESBEGIN OF itab,
    fl1(300)  TYPE c,
END OF itab.

DATAdata_tab TYPE STANDARD TABLE OF itab,
        wa_tab LIKE LINE OF data_tab.

CALL METHOD cl_gui_frontend_services=>gui_upload
EXPORTING
      filename                filename
      filetype                'ASC'
      codepage                '8400'
CHANGING
      data_tab                data_tab
EXCEPTIONS
      file_open_error         1
      file_read_error         2
      no_batch                3
      gui_refuse_filetransfer 4
      no_authority            6
      unknown_error           7
      bad_data_format         8
      unknown_dp_error        12
      access_denied           13
OTHERS                  17.


DATA:lt_dd03l2 TYPE TABLE OF dd03l WITH HEADER LINE.

DATABEGIN OF lt_dd03l OCCURS 0,
    tabname TYPE dd03l-tabname,
    fieldname TYPE dd03l-fieldname,
    keyflag TYPE dd03l-keyflag,
    rollname TYPE dd03l-rollname,
position TYPE dd03l-position,
    inttype TYPE dd03l-inttype,
    leng(6),
decimals(6),
    ddtext TYPE dd03t-ddtext,
    methodname TYPE dd03l-fieldname,
    attrname  TYPE dd03l-fieldname,
END OF lt_dd03l.

DATA:BEGIN OF  fieldname OCCURS 0,
    fieldname TYPE dd03t-fieldname ,
END OF fieldname.
DATA:BEGIN OF rollname OCCURS 0,
    rollname TYPE dd04t-rollname ,
END OF rollname.
DATA:lt_dd03t TYPE TABLE OF dd03t WITH HEADER LINE,
        lt_dd04t TYPE TABLE OF dd04t WITH HEADER LINE.

DATAclsname TYPE string.
DATAitab TYPE TABLE OF string WITH HEADER LINE.
DATAentity TYPE string.
DATApackage TYPE string.
DATApackage_path TYPE string.
LOOP AT data_tab INTO wa_tab.
SPLIT wa_tab AT '|' INTO TABLE itab.
READ TABLE itab INDEX .
    p_table itab.
READ TABLE itab INDEX .
    entity itab.
READ TABLE itab INDEX .
    clsname itab.
READ TABLE itab INDEX 4.
    package itab.
CONDENSE package.
    package_path package.

REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .
REPLACE `.` WITH '\' INTO package_path .


CLEARlt_dd03llt_dd03l[].
SELECT dd03l~tabname dd03l~fieldname keyflag rollname position inttype leng decimals FROM dd03l
INTO CORRESPONDING FIELDS OF TABLE lt_dd03l
WHERE as4local 'A' AND dd03l~tabname p_table AND dd03l~fieldname <> '.INCLU--AP' AND dd03l~fieldname <> '.INCLUDE' ORDER BY position.

SORT lt_dd03l BY position.

LOOP AT lt_dd03l .
IF lt_dd03l-rollname ''.
APPEND lt_dd03l-fieldname TO fieldname.
ELSE.
APPEND lt_dd03l-rollname TO rollname.
ENDIF.
ENDLOOP.


IF fieldname[] IS NOT INITIAL.
SELECT fieldname ddtext INTO CORRESPONDING FIELDS OF TABLE lt_dd03t
FROM dd03t
FOR ALL ENTRIES IN fieldname
WHERE tabname p_table
AND ddlanguage '1'
AND fieldname fieldname-fieldname.
ENDIF.

IF rollname[] IS NOT INITIAL.
SELECT rollname ddtext INTO CORRESPONDING FIELDS OF TABLE lt_dd04t
FROM dd04t
FOR ALL ENTRIES IN rollname
WHERE ddlanguage '1'
AND rollname rollname-rollname.
ENDIF.
DATATYPE i.
FIELD-SYMBOLS <lt_dd03l> LIKE LINE OF lt_dd03l .
LOOP AT lt_dd03l  ASSIGNING <lt_dd03l>.
IF <lt_dd03l>-fieldname 'SHORT'.
        <lt_dd03l>-fieldname 'SHORT_'.
ENDIF.
<lt_dd03l>-leng.
      <lt_dd03l>-leng i.
<lt_dd03l>-decimals.
      <lt_dd03l>-decimals i.
      <lt_dd03l>-methodname <lt_dd03l>-fieldname.

*      IF <lt_dd03l>-inttype = 'P' .
*        <lt_dd03l>-leng  = <lt_dd03l>-leng  * 2 + 1.
*      ENDIF.
IF  <lt_dd03l>-inttype 'I' OR <lt_dd03l>-inttype 'X'.
        <lt_dd03l>-leng  11.
ENDIF.
TRANSLATE <lt_dd03l>-methodname TO LOWER CASE.
CONCATENATE <lt_dd03l>-fieldname+0(1<lt_dd03l>-methodname+1 INTO <lt_dd03l>-methodname.

      <lt_dd03l>-attrname <lt_dd03l>-fieldname.
TRANSLATE <lt_dd03l>-attrname TO LOWER CASE.


REPLACE `/` WITH '_' INTO <lt_dd03l>-fieldname.
REPLACE `/` WITH '_' INTO <lt_dd03l>-fieldname.
REPLACE `/` WITH '_' INTO <lt_dd03l>-fieldname.
REPLACE `/` WITH '_' INTO <lt_dd03l>-fieldname.
READ TABLE lt_dd03t WITH KEY fieldname <lt_dd03l>-fieldname.
IF sy-subrc 0.
        <lt_dd03l>-ddtext lt_dd03t-ddtext.
ELSE.
READ TABLE lt_dd04t WITH KEY rollname <lt_dd03l>-rollname.
IF sy-subrc 0.
          <lt_dd03l>-ddtext lt_dd04t-ddtext.
ENDIF.
ENDIF.

ENDLOOP.


*    LOOP AT lt_dd03l.
*      WRITE:/ lt_dd03l-fieldname,lt_dd03l-keyflag,lt_dd03l-rollname,lt_dd03l-position,lt_dd03l-inttype,lt_dd03l-leng,lt_dd03l-decimals,lt_dd03l-ddtext.
*    ENDLOOP.

DATAlt_pk TYPE TABLE OF string WITH HEADER LINE.
CLEARlt_pk,lt_pk[].
CONCATENATE `package ` package `;` INTO lt_pk.
APPEND lt_pk.
APPEND `import java.io.Serializable;` TO lt_pk.
APPEND `import javax.persistence.Column;` TO lt_pk.
APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.

CONCATENATE `public class ` clsname `Pk implements Serializable {` INTO lt_pk.
APPEND lt_pk.
APPEND `private static final long serialVersionUID = 1L;` TO lt_pk.
APPEND `private volatile int hashCode;` TO lt_pk.

LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF lt_dd03l-inttype 'P'.
CONCATENATE `private java.math.BigDecimal ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_pk.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `private Integer ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_pk.
ELSE.
CONCATENATE `private String ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_pk.
ENDIF.
APPEND lt_pk.
ENDLOOP.
APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.
CONCATENATE `public ` clsname `Pk() {  }` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public ` clsname `Pk(` INTO lt_pk.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF sy-tabix 1.
IF lt_dd03l-inttype 'P'.
CONCATENATE  lt_pk `java.math.BigDecimal ` lt_dd03l-attrname  INTO lt_pk.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE lt_pk `Integer ` lt_dd03l-attrname INTO lt_pk.
ELSE.
CONCATENATE lt_pk `String ` lt_dd03l-attrname INTO lt_pk.
ENDIF.
ELSE.
IF lt_dd03l-inttype 'P'.
CONCATENATE  lt_pk `,java.math.BigDecimal ` lt_dd03l-attrname  INTO lt_pk.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE lt_pk `,Integer ` lt_dd03l-attrname  INTO lt_pk.
ELSE.
CONCATENATE lt_pk `,String ` lt_dd03l-attrname INTO lt_pk.
ENDIF.
ENDIF.
ENDLOOP.
CONCATENATE lt_pk `) {` INTO lt_pk.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
CONCATENATE lt_pk `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;` INTO lt_pk.
ENDLOOP.
CONCATENATE lt_pk `}` INTO lt_pk.
APPEND  lt_pk.

DATAlen TYPE string.

LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF lt_dd03l-inttype 'P'.
CONCATENATE `public java.math.BigDecimal get` lt_dd03l-methodname `() {` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public ` clsname `Pk set` lt_dd03l-methodname `(java.math.BigDecimal ` lt_dd03l-attrname `) {`INTO lt_pk.
APPEND lt_pk.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_pk.
APPEND lt_pk.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public Integer get` lt_dd03l-methodname `() {` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public ` clsname `Pk set` lt_dd03l-methodname `(Integer ` lt_dd03l-attrname `) {`INTO lt_pk.
APPEND lt_pk.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_pk.
APPEND lt_pk.
ELSE.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public String get` lt_dd03l-methodname `() {` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `public ` clsname `Pk set` lt_dd03l-methodname `(String ` lt_dd03l-attrname `) {`INTO lt_pk.
APPEND lt_pk.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_pk.
APPEND lt_pk.
ENDIF.
ENDLOOP.

APPEND `@Override` TO lt_pk.
APPEND `public int hashCode() {` TO lt_pk.
APPEND `int result = hashCode;` TO lt_pk.
APPEND `if (result == 0) {` TO lt_pk.
APPEND `result = 17;` TO lt_pk.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
CONCATENATE `result = 31 * result + ((` lt_dd03l-attrname ` == null) ? 0 : ` lt_dd03l-attrname `.hashCode());` INTO lt_pk.
APPEND lt_pk.
ENDLOOP.
APPEND `hashCode = result;}return result;}` TO lt_pk.

APPEND `@Override` TO lt_pk.
APPEND `public boolean equals(Object o) {if (o == this) {return true;}` TO lt_pk.

CONCATENATE `if (!(o instanceof ` clsname `Pk)) {return false;}` INTO lt_pk.
APPEND lt_pk.
CONCATENATE clsname `Pk other = (` clsname `Pk) o;` INTO lt_pk.
APPEND lt_pk.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
CONCATENATE `if (` lt_dd03l-attrname ` == null && other.` lt_dd03l-attrname ` != null) {return false;` INTO lt_pk.
APPEND lt_pk.
CONCATENATE `} else if (` lt_dd03l-attrname ` != null &&` ` !` lt_dd03l-attrname `.equals(other.` lt_dd03l-attrname `)) {return false;}` INTO lt_pk.
APPEND lt_pk.
ENDLOOP.


*    LOOP AT lt_dd03l WHERE  keyflag = 'X'.
*      IF sy-tabix = 1.
*        CONCATENATE `return this.` lt_dd03l-attrname `.equals(other.` lt_dd03l-attrname `)` INTO lt_pk.
*        APPEND lt_pk.
*      ELSE.
*        CONCATENATE `&& this.` lt_dd03l-attrname `.equals(other.` lt_dd03l-attrname `)` INTO lt_pk.
*        APPEND lt_pk.
*      ENDIF.
*    ENDLOOP.

APPEND `return true;}` TO lt_pk.

APPEND `@Override` TO lt_pk.
APPEND `public String toString() {` TO lt_pk.
CONCATENATE `return "` clsname `Pk [` INTO lt_pk.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF sy-tabix 1.
CONCATENATE  lt_pk lt_dd03l-attrname `=" + ` lt_dd03l-attrname INTO lt_pk.
ELSE.
CONCATENATE  lt_pk `+ ", ` lt_dd03l-attrname `=" + ` lt_dd03l-attrname INTO lt_pk.
ENDIF.
ENDLOOP.
CONCATENATE  lt_pk `+ "]";}}` INTO lt_pk.
APPEND  lt_pk.





**生成的Java实体Bean主键类
CONCATENATE lv_path `\Bean\` package_path `\` clsname `Pk.java` INTO filename.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
        filename filename
        codepage '4110'
TABLES
        data_tab lt_pk[].

"================================================================================================

DATAlt_class TYPE TABLE OF string WITH HEADER LINE.
CLEARlt_class,lt_class[].

CONCATENATE `package ` package `;` INTO lt_class.
APPEND lt_class.
APPEND `import com.suning.hrqz.entity.BaseEntity;` TO lt_class.
APPEND `import javax.persistence.Column;` TO lt_class.
APPEND `import javax.persistence.Entity;` TO lt_class.
APPEND `import javax.persistence.Id;` TO lt_class.
APPEND `import javax.persistence.IdClass;` TO lt_class.
APPEND `import javax.persistence.Table;` TO lt_class.
APPEND `import javax.persistence.Transient;` TO lt_class.

CONCATENATE `//对应 SAP 表名:` p_table INTO lt_class.
APPEND lt_class.
CONCATENATE `@Entity(name = "` entity `")` INTO lt_class.
APPEND lt_class.
APPEND `@Table(` TO lt_class.
APPEND `// uniqueConstraints = { @UniqueConstraint(name="Unique_Index",columnNames = {"xx","xxx"}) }` TO lt_class.
APPEND `// ,indexes={@Index(name = "index01",columnList="xx,xxx")}` TO lt_class.
APPEND `)` TO lt_class.
CONCATENATE `@IdClass(value = ` clsname `Pk.class)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public class ` clsname ` extends BaseEntity {`  INTO lt_class.
APPEND lt_class.

APPEND `@Transient` TO lt_class.
APPEND `private static final long serialVersionUID = 1L;` TO lt_class.
APPEND `@Transient` TO lt_class.
CONCATENATE `private ` clsname `Pk pk;` INTO lt_class.
APPEND lt_class.
APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.

LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF lt_dd03l-inttype 'P'.
CONCATENATE `private java.math.BigDecimal ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `private Integer ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ELSE.
CONCATENATE `private String ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ENDIF.
APPEND lt_class.
ENDLOOP.

APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.
LOOP AT lt_dd03l WHERE  keyflag <> 'X'.
IF lt_dd03l-inttype 'P'.
CONCATENATE `private java.math.BigDecimal ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `private Integer ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ELSE.
CONCATENATE `private String ` lt_dd03l-attrname `;//` lt_dd03l-ddtext INTO lt_class.
ENDIF.
APPEND lt_class.
ENDLOOP.

CONCATENATE `public ` clsname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `pk = new ` clsname `Pk();}` INTO lt_class.
APPEND lt_class.

CONCATENATE `public ` clsname `(` INTO lt_class.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF sy-tabix 1.
IF lt_dd03l-inttype 'P'.
CONCATENATE  lt_class `java.math.BigDecimal ` lt_dd03l-attrname  INTO lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE lt_class `Integer ` lt_dd03l-attrname  INTO lt_class.
ELSE.
CONCATENATE lt_class `String ` lt_dd03l-attrname INTO lt_class.
ENDIF.
ELSE.
IF lt_dd03l-inttype 'P'.
CONCATENATE  lt_class `,java.math.BigDecimal ` lt_dd03l-attrname  INTO lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE lt_class `,Integer ` lt_dd03l-attrname  INTO lt_class.
ELSE.
CONCATENATE lt_class `,String ` lt_dd03l-attrname INTO lt_class.
ENDIF.
ENDIF.
ENDLOOP.
CONCATENATE lt_class `) {` INTO lt_class.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
CONCATENATE lt_class `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;` INTO lt_class.
ENDLOOP.
APPEND  lt_class.
CONCATENATE `pk = new ` clsname `Pk(` INTO lt_class.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
IF sy-tabix 1.
CONCATENATE lt_class lt_dd03l-fieldname  INTO lt_class.
ELSE.
CONCATENATE lt_class `,` lt_dd03l-fieldname  INTO lt_class.
ENDIF.
ENDLOOP.

APPEND `}` TO lt_class.
APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.

APPEND `@Transient` TO lt_class.
CONCATENATE  `public ` clsname `Pk getPk() {return pk;}` INTO lt_class.
APPEND lt_class.
CONCATENATE  `public ` clsname ` setPk(` clsname `Pk pk) {this.pk = pk;` INTO lt_class.
APPEND lt_class.
LOOP AT lt_dd03l WHERE  keyflag 'X'.
CONCATENATE  `this.` lt_dd03l-attrname ` = pk.get` lt_dd03l-methodname `();` INTO lt_class.
APPEND lt_class.
ENDLOOP.
APPEND `return this;}` TO lt_class.

LOOP AT lt_dd03l WHERE  keyflag 'X'.
APPEND `@Id` TO lt_class.
IF lt_dd03l-inttype 'P'.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", precision = ` lt_dd03l-leng `, scale = ` lt_dd03l-decimals `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public java.math.BigDecimal get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(java.math.BigDecimal ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;pk.set` lt_dd03l-methodname `(` lt_dd03l-attrname `);return this;}` INTO lt_class.
APPEND lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public Integer get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(Integer ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;pk.set` lt_dd03l-methodname `(` lt_dd03l-attrname `);return this;}` INTO lt_class.
APPEND lt_class.
ELSE.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public String get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(String ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;pk.set` lt_dd03l-methodname `(` lt_dd03l-attrname `);return this;}` INTO lt_class.
APPEND lt_class.
ENDIF.

ENDLOOP.



APPEND  cl_abap_char_utilities=>cr_lf TO lt_pk.

LOOP AT lt_dd03l WHERE  keyflag <> 'X'.
IF lt_dd03l-inttype 'P'.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", precision = ` lt_dd03l-leng `, scale = ` lt_dd03l-decimals `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public java.math.BigDecimal get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(java.math.BigDecimal ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_class.
APPEND lt_class.
ELSEIF lt_dd03l-inttype 'I' OR lt_dd03l-inttype 'X'.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public Integer get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(Integer ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_class.
APPEND lt_class.
ELSE.
CONCATENATE `@Column(name = "` lt_dd03l-fieldname `", length = ` lt_dd03l-leng `)` INTO lt_class.
APPEND lt_class.
CONCATENATE `public String get` lt_dd03l-methodname `() {` INTO lt_class.
APPEND lt_class.
CONCATENATE `return ` lt_dd03l-attrname `;}` INTO lt_class.
APPEND lt_class.
CONCATENATE `public ` clsname ` set` lt_dd03l-methodname `(String ` lt_dd03l-attrname `) {`INTO lt_class.
APPEND lt_class.
CONCATENATE `this.` lt_dd03l-attrname ` = ` lt_dd03l-attrname `;return this;}` INTO lt_class.
APPEND lt_class.
ENDIF.
ENDLOOP.


APPEND `@Override` TO lt_class.
APPEND `public int hashCode() {return pk.hashCode();}` TO lt_class.
APPEND `@Override` TO lt_class.
APPEND `public boolean equals(Object o) {` TO lt_class.
CONCATENATE `if (!(o instanceof ` clsname `)) {` `` INTO lt_class.
APPEND  lt_class.
CONCATENATE `return false;}` clsname ` other = (` clsname `) o;` INTO lt_class.
APPEND  lt_class.
*    CONCATENATE `return pk.equals(new ` clsname `Pk(` INTO lt_class.
*    LOOP AT lt_dd03l WHERE  keyflag = 'X'.
*      IF sy-tabix = 1.
*        CONCATENATE lt_class `other.` lt_dd03l-attrname  INTO lt_class.
*      ELSE.
*        CONCATENATE lt_class `,other.` lt_dd03l-attrname  INTO lt_class.
*      ENDIF.
*    ENDLOOP.
*    CONCATENATE lt_class `));}` INTO lt_class.
*    APPEND  lt_class.
APPEND `return pk.equals(other.getPk());}` to lt_class.

APPEND `@Override` TO lt_class.
APPEND `public String toString() {` TO lt_class.
CONCATENATE `return "` clsname ` [pk=" + pk` INTO lt_class.
LOOP AT lt_dd03l WHERE  keyflag <> 'X'.
CONCATENATE lt_class `+ ", ` lt_dd03l-attrname   `=" + ` lt_dd03l-attrname INTO lt_class.
ENDLOOP.
APPEND  lt_class.
APPEND `+ "]";}` TO lt_class.
APPEND `}` TO lt_class.

***生成的Java实体Bean
CONCATENATE lv_path `\Bean\` package_path `\` clsname `.java` INTO filename.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
        filename filename
        codepage '4110'
TABLES
        data_tab lt_class[].
ENDLOOP.


比如要将PA0000与PA0001两个表导出,配置文件:

生成的Java实体如下:
package com.xxx;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import javax.persistence.Transient;
//对应 SAP 表名:PA0000
@Entity(name = "HR_PA0000")
@Table(
// uniqueConstraints = { @UniqueConstraint(name="Unique_Index",columnNames =
// {"xx","xxx"}) }
// ,indexes={@Index(name = "index01",columnList="xx,xxx")}
)
@IdClass(value = Pa0000Pk.class)
public class Pa0000 extends BaseEntity {
    @Transient
    private static final long serialVersionUID = 1L;
    @Transient
    private Pa0000Pk pk;
    private String mandt;// 客户端
    private String pernr;// 人员号
    private String subty;// 子信息类型
    private String objps;// 对象标识
    private String sprps;// 人力资源主数据记录的锁定标志
    private String endda;// 结束日期
    private String begda;// 开始日期
    private String seqnr;// 相同关键值信息类型记录的编号
    private String aedtm;// 更改日期
    private String uname;// 对象更改人员的名称
    private String histo;// 历史记录标志
    private String itxex;// 信息类型的文本存在
    private String refex;// 参考字段存在 (主/次级成本)
    private String ordex;// 确定字段存在
    private String itbld;// 信息类型屏幕控制
    private String preas;// 更改主数据的原因
    private String flag1;// 保留字段/未使用字段
    private String flag2;// 保留字段/未使用字段
    private String flag3;// 保留字段/未使用字段
    private String flag4;// 保留字段/未使用字段
    private String rese1;// 长度为 2 的保留字段/未使用字段
    private String rese2;// 长度为 2 的保留字段/未使用字段
    private String grpvl;// 关于个人分配的分组值
    private String massn;// 操作类型
    private String massg;// 操作原因
    private String stat1;// 客户特定状态
    private String stat2;// 雇佣状态
    private String stat3;// 特殊支付状态
    private String zsqlx;// 申请类型
    public Pa0000() {
        pk = new Pa0000Pk();
    }
    public Pa0000(String mandt, String pernr, String subty, String objps, String sprps, String endda, String begda,
            String seqnr) {
        this.mandt = mandt;
        this.pernr = pernr;
        this.subty = subty;
        this.objps = objps;
        this.sprps = sprps;
        this.endda = endda;
        this.begda = begda;
        this.seqnr = seqnr;
    }
    @Transient
    public Pa0000Pk getPk() {
        return pk;
    }
    public Pa0000 setPk(Pa0000Pk pk) {
        this.pk = pk;
        this.mandt = pk.getMandt();
        this.pernr = pk.getPernr();
        this.subty = pk.getSubty();
        this.objps = pk.getObjps();
        this.sprps = pk.getSprps();
        this.endda = pk.getEndda();
        this.begda = pk.getBegda();
        this.seqnr = pk.getSeqnr();
        return this;
    }
    @Id
    @Column(name = "MANDT", length = 3)
    public String getMandt() {
        return mandt;
    }
    public Pa0000 setMandt(String mandt) {
        this.mandt = mandt;
        pk.setMandt(mandt);
        return this;
    }
    @Id
    @Column(name = "PERNR", length = 8)
    public String getPernr() {
        return pernr;
    }
    public Pa0000 setPernr(String pernr) {
        this.pernr = pernr;
        pk.setPernr(pernr);
        return this;
    }
    @Id
    @Column(name = "SUBTY", length = 4)
    public String getSubty() {
        return subty;
    }
    public Pa0000 setSubty(String subty) {
        this.subty = subty;
        pk.setSubty(subty);
        return this;
    }
    @Id
    @Column(name = "OBJPS", length = 2)
    public String getObjps() {
        return objps;
    }
    public Pa0000 setObjps(String objps) {
        this.objps = objps;
        pk.setObjps(objps);
        return this;
    }
    @Id
    @Column(name = "SPRPS", length = 1)
    public String getSprps() {
        return sprps;
    }
    public Pa0000 setSprps(String sprps) {
        this.sprps = sprps;
        pk.setSprps(sprps);
        return this;
    }
    @Id
    @Column(name = "ENDDA", length = 8)
    public String getEndda() {
        return endda;
    }
    public Pa0000 setEndda(String endda) {
        this.endda = endda;
        pk.setEndda(endda);
        return this;
    }
    @Id
    @Column(name = "BEGDA", length = 8)
    public String getBegda() {
        return begda;
    }
    public Pa0000 setBegda(String begda) {
        this.begda = begda;
        pk.setBegda(begda);
        return this;
    }
    @Id
    @Column(name = "SEQNR", length = 3)
    public String getSeqnr() {
        return seqnr;
    }
    public Pa0000 setSeqnr(String seqnr) {
        this.seqnr = seqnr;
        pk.setSeqnr(seqnr);
        return this;
    }
    @Column(name = "AEDTM", length = 8)
    public String getAedtm() {
        return aedtm;
    }
    public Pa0000 setAedtm(String aedtm) {
        this.aedtm = aedtm;
        return this;
    }
    @Column(name = "UNAME", length = 12)
    public String getUname() {
        return uname;
    }
    public Pa0000 setUname(String uname) {
        this.uname = uname;
        return this;
    }
    @Column(name = "HISTO", length = 1)
    public String getHisto() {
        return histo;
    }
    public Pa0000 setHisto(String histo) {
        this.histo = histo;
        return this;
    }
    @Column(name = "ITXEX", length = 1)
    public String getItxex() {
        return itxex;
    }
    public Pa0000 setItxex(String itxex) {
        this.itxex = itxex;
        return this;
    }
    @Column(name = "REFEX", length = 1)
    public String getRefex() {
        return refex;
    }
    public Pa0000 setRefex(String refex) {
        this.refex = refex;
        return this;
    }
    @Column(name = "ORDEX", length = 1)
    public String getOrdex() {
        return ordex;
    }
    public Pa0000 setOrdex(String ordex) {
        this.ordex = ordex;
        return this;
    }
    @Column(name = "ITBLD", length = 2)
    public String getItbld() {
        return itbld;
    }
    public Pa0000 setItbld(String itbld) {
        this.itbld = itbld;
        return this;
    }
    @Column(name = "PREAS", length = 2)
    public String getPreas() {
        return preas;
    }
    public Pa0000 setPreas(String preas) {
        this.preas = preas;
        return this;
    }
    @Column(name = "FLAG1", length = 1)
    public String getFlag1() {
        return flag1;
    }
    public Pa0000 setFlag1(String flag1) {
        this.flag1 = flag1;
        return this;
    }
    @Column(name = "FLAG2", length = 1)
    public String getFlag2() {
        return flag2;
    }
    public Pa0000 setFlag2(String flag2) {
        this.flag2 = flag2;
        return this;
    }
    @Column(name = "FLAG3", length = 1)
    public String getFlag3() {
        return flag3;
    }
    public Pa0000 setFlag3(String flag3) {
        this.flag3 = flag3;
        return this;
    }
    @Column(name = "FLAG4", length = 1)
    public String getFlag4() {
        return flag4;
    }
    public Pa0000 setFlag4(String flag4) {
        this.flag4 = flag4;
        return this;
    }
    @Column(name = "RESE1", length = 2)
    public String getRese1() {
        return rese1;
    }
    public Pa0000 setRese1(String rese1) {
        this.rese1 = rese1;
        return this;
    }
    @Column(name = "RESE2", length = 2)
    public String getRese2() {
        return rese2;
    }
    public Pa0000 setRese2(String rese2) {
        this.rese2 = rese2;
        return this;
    }
    @Column(name = "GRPVL", length = 4)
    public String getGrpvl() {
        return grpvl;
    }
    public Pa0000 setGrpvl(String grpvl) {
        this.grpvl = grpvl;
        return this;
    }
    @Column(name = "MASSN", length = 2)
    public String getMassn() {
        return massn;
    }
    public Pa0000 setMassn(String massn) {
        this.massn = massn;
        return this;
    }
    @Column(name = "MASSG", length = 2)
    public String getMassg() {
        return massg;
    }
    public Pa0000 setMassg(String massg) {
        this.massg = massg;
        return this;
    }
    @Column(name = "STAT1", length = 1)
    public String getStat1() {
        return stat1;
    }
    public Pa0000 setStat1(String stat1) {
        this.stat1 = stat1;
        return this;
    }
    @Column(name = "STAT2", length = 1)
    public String getStat2() {
        return stat2;
    }
    public Pa0000 setStat2(String stat2) {
        this.stat2 = stat2;
        return this;
    }
    @Column(name = "STAT3", length = 1)
    public String getStat3() {
        return stat3;
    }
    public Pa0000 setStat3(String stat3) {
        this.stat3 = stat3;
        return this;
    }
    @Column(name = "ZSQLX", length = 2)
    public String getZsqlx() {
        return zsqlx;
    }
    public Pa0000 setZsqlx(String zsqlx) {
        this.zsqlx = zsqlx;
        return this;
    }
    @Override
    public int hashCode() {
        return pk.hashCode();
    }
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pa0000)) {
            return false;
        }
        Pa0000 other = (Pa0000) o;
        return pk.equals(other.getPk());
    }
    @Override
    public String toString() {
        return "Pa0000 [pk=" + pk + ", aedtm=" + aedtm + ", uname=" + uname + ", histo=" + histo + ", itxex=" + itxex
                + ", refex=" + refex + ", ordex=" + ordex + ", itbld=" + itbld + ", preas=" + preas + ", flag1=" + flag1
                + ", flag2=" + flag2 + ", flag3=" + flag3 + ", flag4=" + flag4 + ", rese1=" + rese1 + ", rese2=" + rese2
                + ", grpvl=" + grpvl + ", massn=" + massn + ", massg=" + massg + ", stat1=" + stat1 + ", stat2=" + stat2
                + ", stat3=" + stat3 + ", zsqlx=" + zsqlx + "]";
    }
}

package com.xxx;
import java.io.Serializable;
import javax.persistence.Column;
public class Pa0000Pk implements Serializable {
    private static final long serialVersionUID = 1L;
    private volatile int hashCode;
    private String mandt;// 客户端
    private String pernr;// 人员号
    private String subty;// 子信息类型
    private String objps;// 对象标识
    private String sprps;// 人力资源主数据记录的锁定标志
    private String endda;// 结束日期
    private String begda;// 开始日期
    private String seqnr;// 相同关键值信息类型记录的编号
    public Pa0000Pk() {
    }
    public Pa0000Pk(String mandt, String pernr, String subty, String objps, String sprps, String endda, String begda,
            String seqnr) {
        this.mandt = mandt;
        this.pernr = pernr;
        this.subty = subty;
        this.objps = objps;
        this.sprps = sprps;
        this.endda = endda;
        this.begda = begda;
        this.seqnr = seqnr;
    }
    @Column(name = "MANDT", length = 3)
    public String getMandt() {
        return mandt;
    }
    public Pa0000Pk setMandt(String mandt) {
        this.mandt = mandt;
        return this;
    }
    @Column(name = "PERNR", length = 8)
    public String getPernr() {
        return pernr;
    }
    public Pa0000Pk setPernr(String pernr) {
        this.pernr = pernr;
        return this;
    }
    @Column(name = "SUBTY", length = 4)
    public String getSubty() {
        return subty;
    }
    public Pa0000Pk setSubty(String subty) {
        this.subty = subty;
        return this;
    }
    @Column(name = "OBJPS", length = 2)
    public String getObjps() {
        return objps;
    }
    public Pa0000Pk setObjps(String objps) {
        this.objps = objps;
        return this;
    }
    @Column(name = "SPRPS", length = 1)
    public String getSprps() {
        return sprps;
    }
    public Pa0000Pk setSprps(String sprps) {
        this.sprps = sprps;
        return this;
    }
    @Column(name = "ENDDA", length = 8)
    public String getEndda() {
        return endda;
    }
    public Pa0000Pk setEndda(String endda) {
        this.endda = endda;
        return this;
    }
    @Column(name = "BEGDA", length = 8)
    public String getBegda() {
        return begda;
    }
    public Pa0000Pk setBegda(String begda) {
        this.begda = begda;
        return this;
    }
    @Column(name = "SEQNR", length = 3)
    public String getSeqnr() {
        return seqnr;
    }
    public Pa0000Pk setSeqnr(String seqnr) {
        this.seqnr = seqnr;
        return this;
    }
    @Override
    public int hashCode() {
        int result = hashCode;
        if (result == 0) {
            result = 17;
            result = 31 * result + ((mandt == null) ? 0 : mandt.hashCode());
            result = 31 * result + ((pernr == null) ? 0 : pernr.hashCode());
            result = 31 * result + ((subty == null) ? 0 : subty.hashCode());
            result = 31 * result + ((objps == null) ? 0 : objps.hashCode());
            result = 31 * result + ((sprps == null) ? 0 : sprps.hashCode());
            result = 31 * result + ((endda == null) ? 0 : endda.hashCode());
            result = 31 * result + ((begda == null) ? 0 : begda.hashCode());
            result = 31 * result + ((seqnr == null) ? 0 : seqnr.hashCode());
            hashCode = result;
        }
        return result;
    }
    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof Pa0000Pk)) {
            return false;
        }
        Pa0000Pk other = (Pa0000Pk) o;
        if (mandt == null && other.mandt != null) {
            return false;
        } else if (mandt != null && !mandt.equals(other.mandt)) {
            return false;
        }
        if (pernr == null && other.pernr != null) {
            return false;
        } else if (pernr != null && !pernr.equals(other.pernr)) {
            return false;
        }
        if (subty == null && other.subty != null) {
            return false;
        } else if (subty != null && !subty.equals(other.subty)) {
            return false;
        }
        if (objps == null && other.objps != null) {
            return false;
        } else if (objps != null && !objps.equals(other.objps)) {
            return false;
        }
        if (sprps == null && other.sprps != null) {
            return false;
        } else if (sprps != null && !sprps.equals(other.sprps)) {
            return false;
        }
        if (endda == null && other.endda != null) {
            return false;
        } else if (endda != null && !endda.equals(other.endda)) {
            return false;
        }
        if (begda == null && other.begda != null) {
            return false;
        } else if (begda != null && !begda.equals(other.begda)) {
            return false;
        }
        if (seqnr == null && other.seqnr != null) {
            return false;
        } else if (seqnr != null && !seqnr.equals(other.seqnr)) {
            return false;
        }
        return true;
    }
    @Override
    public String toString() {
        return "Pa0000Pk [mandt=" + mandt + ", pernr=" + pernr + ", subty=" + subty + ", objps=" + objps + ", sprps="
                + sprps + ", endda=" + endda + ", begda=" + begda + ", seqnr=" + seqnr + "]";
    }
}


上面是PA0000这个表所生成的实体Bean,每张会生成两个类,PK结尾的是主键,另一个是非主键Bean。另外,除了ABAP表的字段外,可能还需扩展几个字段,这些扩展字段可以放在 BaseEntity 父类里:
package com.xxx;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
@MappedSuperclass
public class BaseEntity implements Serializable {
    @Transient
    private static final long serialVersionUID = 1L;
    @Transient
    private String module;// 表所属模块
    @Transient
    private String tableName;// 表名
    private String insertTime;// 数据插入时间
    private String lastUpdateTime;// 数据最后一次更新时间
    private String deleteFlg;// 是否被删除了
    @Column(length = 14, name = "INSERT_TIME", updatable = false)
    public String getInsertTime() {
        return insertTime;
    }
    public void setInsertTime(String insertTime) {
        this.insertTime = insertTime;
    }
    @Column(length = 14, name = "LAST_UPDATE_TIME")
    public String getLastUpdateTime() {
        return lastUpdateTime;
    }
    public void setLastUpdateTime(String lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }
    @Column(length = 1, name = "DELETE_FLG")
    public String getDeleteFlg() {
        return deleteFlg;
    }
    public void setDeleteFlg(String deleteFlg) {
        this.deleteFlg = deleteFlg;
    }
    @Transient
    public String getModule() {
        return module;
    }
    public void setModule(String module) {
        this.module = module;
    }
    @Transient
    public String getTableName() {
        return tableName;
    }
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }
}

生成这些实体Bean类后,然后使用Hibernate持久化框架就可以自动生成表了,这里不再演示,做过Java Web开发的都知道,Easy.....不过要注意的是,Hibernate根据实体类生成表时,发现字段顺序与实体Bean中定义的字段顺序不一样,这也就与ABAP表字段顺序不一样了,这是Hibernate的问题,可以修改Hibernate里相应Jar包里这个类,并将它替换掉即可:
注意Hibernate版本是4.3.8的,下面是经过修改后的类,编译后替换原Jar包中相应的类即可:
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
// $Id$
package org.hibernate.cfg;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.persistence.Access;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;
/**
 * A helper class to keep the {@code XProperty}s of a class ordered by access
 * type.
 * 
 * @author Hardy Ferentschik
 */
class PropertyContainer {
    static {
        System.setProperty("jboss.i18n.generate-proxies""true");
    }
    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
            PropertyContainer.class.getName());
    private final AccessType explicitClassDefinedAccessType;
    /**
     * Constains the properties which must be returned in case the class is accessed
     * via {@code AccessType.FIELD}. Note, this does not mean that all
     * {@code XProperty}s in this map are fields. Due to JPA access rules single
     * properties can have different access type than the overall class access type.
     */
    private final LinkedHashMap<String, XProperty> fieldAccessMap;
    /**
     * Constains the properties which must be returned in case the class is accessed
     * via {@code AccessType.Property}. Note, this does not mean that all
     * {@code XProperty}s in this map are properties/methods. Due to JPA access
     * rules single properties can have different access type than the overall class
     * access type.
     */
    private final LinkedHashMap<String, XProperty> propertyAccessMap;
    private static LinkedHashMap<String, XProperty> fieldAccessMapBase;
    private static LinkedHashMap<String, XProperty> propertyAccessMapBase;
    /**
     * The class for which this container is created.
     */
    private final XClass xClass;
    private final XClass entityAtStake;
    PropertyContainer(XClass clazz, XClass entityAtStake) {
        this.xClass = clazz;
        this.entityAtStake = entityAtStake;
        explicitClassDefinedAccessType = determineClassDefinedAccessStrategy();
        // first add all properties to field and property map
        if (xClass.getName().toLowerCase().endsWith("baseentity")) {
            if (fieldAccessMapBase == null) {
                fieldAccessMapBase = initProperties(AccessType.FIELD);
                propertyAccessMapBase = initProperties(AccessType.PROPERTY);
            }
            fieldAccessMap = new LinkedHashMap<String, XProperty>();
            propertyAccessMap = new LinkedHashMap<String, XProperty>();
        } else {
            fieldAccessMap = initProperties(AccessType.FIELD);
            propertyAccessMap = initProperties(AccessType.PROPERTY);
        }
        considerExplicitFieldAndPropertyAccess();
    }
    public XClass getEntityAtStake() {
        return entityAtStake;
    }
    public XClass getDeclaringClass() {
        return xClass;
    }
    public AccessType getExplicitAccessStrategy() {
        return explicitClassDefinedAccessType;
    }
    public boolean hasExplicitAccessStrategy() {
        return !explicitClassDefinedAccessType.equals(AccessType.DEFAULT);
    }
    public Collection<XProperty> getProperties(AccessType accessType) {
        assertTypesAreResolvable(accessType);
        if (AccessType.DEFAULT == accessType || AccessType.PROPERTY == accessType) {
            return Collections.unmodifiableCollection(propertyAccessMap.values());
        } else {
            return Collections.unmodifiableCollection(fieldAccessMap.values());
        }
    }
    private void assertTypesAreResolvable(AccessType access) {
        Map<String, XProperty> xprops;
        if (AccessType.PROPERTY.equals(access) || AccessType.DEFAULT.equals(access)) {
            xprops = propertyAccessMap;
        } else {
            xprops = fieldAccessMap;
        }
        for (XProperty property : xprops.values()) {
            if (!property.isTypeResolved() && !discoverTypeWithoutReflection(property)) {
                String msg = "Property " + StringHelper.qualify(xClass.getName(), property.getName())
                        + " has an unbound type and no explicit target entity. Resolve this Generic usage issue"
                        + " or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type";
                throw new AnnotationException(msg);
            }
        }
    }
    private void considerExplicitFieldAndPropertyAccess() {
        for (XProperty property : fieldAccessMap.values()) {
            Access access = property.getAnnotation(Access.class);
            if (access == null) {
                continue;
            }
            // see "2.3.2 Explicit Access Type" of JPA 2 spec
            // the access type for this property is explicitly set to
            // AccessType.FIELD, hence we have to
            // use field access for this property even if the default access
            // type for the class is AccessType.PROPERTY
            AccessType accessType = AccessType.getAccessStrategy(access.value());
            if (accessType == AccessType.FIELD) {
                propertyAccessMap.put(property.getName(), property);
                System.out.println("considerExplicitFieldAndPropertyAccess=propertyAccessMap========"
                        + property.getName() + "--" + property);
            } else {
                LOG.debug("Placing @Access(AccessType.FIELD) on a field does not have any effect.");
            }
        }
        for (XProperty property : propertyAccessMap.values()) {
            Access access = property.getAnnotation(Access.class);
            if (access == null) {
                continue;
            }
            AccessType accessType = AccessType.getAccessStrategy(access.value());
            // see "2.3.2 Explicit Access Type" of JPA 2 spec
            // the access type for this property is explicitly set to
            // AccessType.PROPERTY, hence we have to
            // return use method access even if the default class access type is
            // AccessType.FIELD
            if (accessType == AccessType.PROPERTY) {
                fieldAccessMap.put(property.getName(), property);
                System.out.println("considerExplicitFieldAndPropertyAccess=fieldAccessMap========" + property.getName()
                        + "--" + property);
            } else {
                LOG.debug("Placing @Access(AccessType.PROPERTY) on a field does not have any effect.");
            }
        }
    }
    /**
     * Retrieves all properties from the {@code xClass} with the specified access
     * type. This method does not take any jpa access rules/annotations into account
     * yet.
     * 
     * @param access
     *            The access type - {@code AccessType.FIELD} or
     *            {@code AccessType.Property}
     * 
     * @return A maps of the properties with the given access type keyed against
     *         their property name
     */
    private LinkedHashMap<String, XProperty> initProperties(AccessType access) {
        if (!(AccessType.PROPERTY.equals(access) || AccessType.FIELD.equals(access))) {
            throw new IllegalArgumentException("Access type has to be AccessType.FIELD or AccessType.Property");
        }
        // order so that property are used in the same order when binding native
        // query
        LinkedHashMap<String, XProperty> propertiesMap = new LinkedHashMap<String, XProperty>();
        List<XProperty> properties = xClass.getDeclaredProperties(access.getType());
        List<XProperty> properties2 = xClass.getDeclaredProperties(AccessType.FIELD.getType());
        List<XProperty> propertiess = new LinkedList<XProperty>();
        for (Iterator<XProperty> iterator = properties2.iterator(); iterator.hasNext();) {
            XProperty xProperty = (XProperty) iterator.next();
            for (Iterator<XProperty> iterator2 = properties.iterator(); iterator2.hasNext();) {
                XProperty xProperty2 = (XProperty) iterator2.next();
                if (xProperty.getName().equals(xProperty2.getName())) {
                    propertiess.add(xProperty2);
                    break;
                }
            }
        }
        properties = propertiess;
        for (XProperty property : properties) {
            if (mustBeSkipped(property)) {
                continue;
            }
            propertiesMap.put(property.getName(), property);
        }
        if (!xClass.getName().toLowerCase().endsWith("baseentity") && !xClass.getName().toLowerCase().endsWith("_pk")
                && !xClass.getName().toLowerCase().endsWith("pk")) {
            if (AccessType.FIELD.equals(access)) {
                propertiesMap.putAll(fieldAccessMapBase);
            } else {
                propertiesMap.putAll(propertyAccessMapBase);
            }
        }
        return propertiesMap;
    }
    private AccessType determineClassDefinedAccessStrategy() {
        AccessType classDefinedAccessType;
        AccessType hibernateDefinedAccessType = AccessType.DEFAULT;
        AccessType jpaDefinedAccessType = AccessType.DEFAULT;
        org.hibernate.annotations.AccessType accessType = xClass
                .getAnnotation(org.hibernate.annotations.AccessType.class);
        if (accessType != null) {
            hibernateDefinedAccessType = AccessType.getAccessStrategy(accessType.value());
        }
        Access access = xClass.getAnnotation(Access.class);
        if (access != null) {
            jpaDefinedAccessType = AccessType.getAccessStrategy(access.value());
        }
        if (hibernateDefinedAccessType != AccessType.DEFAULT && jpaDefinedAccessType != AccessType.DEFAULT
                && hibernateDefinedAccessType != jpaDefinedAccessType) {
            throw new MappingException(
                    "@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. ");
        }
        if (hibernateDefinedAccessType != AccessType.DEFAULT) {
            classDefinedAccessType = hibernateDefinedAccessType;
        } else {
            classDefinedAccessType = jpaDefinedAccessType;
        }
        return classDefinedAccessType;
    }
    private static boolean discoverTypeWithoutReflection(XProperty p) {
        if (p.isAnnotationPresent(OneToOne.class)
                && !p.getAnnotation(OneToOne.class).targetEntity().equals(void.class)) {
            return true;
        } else if (p.isAnnotationPresent(OneToMany.class)
                && !p.getAnnotation(OneToMany.class).targetEntity().equals(void.class)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToOne.class)
                && !p.getAnnotation(ManyToOne.class).targetEntity().equals(void.class)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToMany.class)
                && !p.getAnnotation(ManyToMany.class).targetEntity().equals(void.class)) {
            return true;
        } else if (p.isAnnotationPresent(org.hibernate.annotations.Any.class)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToAny.class)) {
            if (!p.isCollection() && !p.isArray()) {
                throw new AnnotationException("@ManyToAny used on a non collection non array property: " + p.getName());
            }
            return true;
        } else if (p.isAnnotationPresent(Type.class)) {
            return true;
        } else if (p.isAnnotationPresent(Target.class)) {
            return true;
        }
        return false;
    }
    private static boolean mustBeSkipped(XProperty property) {
        // TODO make those hardcoded tests more portable (through the bytecode
        // provider?)
        return property.isAnnotationPresent(Transient.class)
                || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals(property.getType().getName())
                || "org.hibernate.bytecode.internal.javassist.FieldHandler".equals(property.getType().getName());
    }
}

posted @ 2018-01-25 12:51  江正军  阅读(...)  评论(... 编辑 收藏