1 29 30 package com.caucho.amber.gen; 31 32 import com.caucho.amber.field.*; 33 import com.caucho.amber.table.Column; 34 import com.caucho.amber.table.Table; 35 import com.caucho.amber.type.EntityType; 36 import com.caucho.amber.type.RelatedType; 37 import com.caucho.amber.type.SubEntityType; 38 import com.caucho.amber.type.Type; 39 import com.caucho.bytecode.*; 40 import com.caucho.java.JavaWriter; 41 import com.caucho.java.gen.ClassComponent; 42 import com.caucho.loader.Environment; 43 import com.caucho.util.L10N; 44 import com.caucho.vfs.PersistentDependency; 45 46 import javax.persistence.CascadeType; 47 import java.io.IOException ; 48 import java.util.ArrayList ; 49 import java.util.HashSet ; 50 51 54 public class EntityComponent extends ClassComponent { 55 private static final L10N L = new L10N(EntityComponent.class); 56 57 private String _baseClassName; 58 private String _extClassName; 59 60 private EntityType _entityType; 61 62 private ArrayList <PersistentDependency> _dependencies = 63 new ArrayList <PersistentDependency>(); 64 65 public EntityComponent() 66 { 67 } 68 69 72 public void setEntityType(EntityType entityType) 73 { 74 _entityType = entityType; 75 76 _dependencies.addAll(entityType.getDependencies()); 77 78 for (int i = 0; i < _dependencies.size(); i++) 79 Environment.addDependency(_dependencies.get(i)); 80 } 81 82 85 public void setBaseClassName(String baseClassName) 86 { 87 _baseClassName = baseClassName; 88 } 89 90 93 public String getBaseClassName() 94 { 95 return _baseClassName; 96 } 97 98 101 public void setExtClassName(String extClassName) 102 { 103 _extClassName = extClassName; 104 } 105 106 109 public String getClassName() 110 { 111 return _extClassName; 112 } 113 114 117 public String getBeanClassName() 118 { 119 return _baseClassName; 121 } 122 123 126 public ArrayList <PersistentDependency> getDependencies() 127 { 128 return _dependencies; 129 } 130 131 134 public void generate(JavaWriter out) 135 throws IOException 136 { 137 try { 138 generateHeader(out); 139 140 generateInit(out); 141 142 HashSet <Object > completedSet = new HashSet <Object >(); 143 144 generatePrologue(out, completedSet); 145 146 generateGetEntityType(out); 147 148 if (_entityType.getParentType() == null) 149 generateGetEntityState(out); 150 151 generateMatch(out); 152 153 generateFields(out); 154 155 generateMethods(out); 156 157 generateDetach(out); 158 159 generateLoad(out); 160 161 int min = 0; 162 if (_entityType.getParentType() != null) 163 min = _entityType.getParentType().getLoadGroupIndex() + 1; 164 int max = _entityType.getLoadGroupIndex(); 165 166 for (int i = min; i <= max; i++) 167 generateLoadGroup(out, i); 168 169 generateResultSetLoad(out); 170 171 generateSetQuery(out); 172 173 175 177 generateCopy(out); 178 179 generateMakePersistent(out); 180 181 generateCascadePersist(out); 182 183 generateCascadeRemove(out); 184 185 generateCreate(out); 186 187 generateDelete(out); 188 189 generateDeleteForeign(out); 190 191 generateFlush(out); 192 193 generateAfterCommit(out); 194 195 generateAfterRollback(out); 196 197 generateHome(out); 198 199 generateInternals(out); 200 201 } catch (IOException e) { 203 throw e; 204 } 205 } 206 207 210 private void generateHeader(JavaWriter out) 211 throws IOException 212 { 213 out.println("/*"); 214 out.println(" * Generated by Resin Amber"); 215 out.println(" * " + com.caucho.Version.VERSION); 216 out.println(" */"); 217 out.print("private static final java.util.logging.Logger __caucho_log = "); 218 out.println("java.util.logging.Logger.getLogger(\"" + getBeanClassName() + "\");"); 219 220 if (_entityType.getParentType() == null) { 221 out.println(); 222 out.println("protected transient com.caucho.amber.type.EntityType __caucho_home;"); 223 out.println("public transient com.caucho.amber.entity.EntityItem __caucho_item;"); 224 out.println("protected transient com.caucho.amber.manager.AmberConnection __caucho_session;"); 225 out.println("protected transient int __caucho_state;"); 226 227 int loadCount = _entityType.getLoadGroupIndex(); 228 for (int i = 0; i <= loadCount / 64; i++) { 229 out.println("protected transient long __caucho_loadMask_" + i + ";"); 230 } 231 232 int dirtyCount = _entityType.getDirtyIndex(); 233 234 for (int i = 0; i <= dirtyCount / 64; i++) { 235 out.println("protected transient long __caucho_dirtyMask_" + i + ";"); 236 out.println("protected transient long __caucho_updateMask_" + i + ";"); 237 } 238 239 out.println("protected transient boolean __caucho_inc_version;"); 240 } 241 } 242 243 246 private void generateInit(JavaWriter out) 247 throws IOException 248 { 249 if (_entityType.getParentType() != null) 250 return; 251 252 275 276 String className = getClassName(); 277 int p = className.lastIndexOf('.'); 278 if (p > 0) 279 className = className.substring(p + 1); 280 281 ArrayList <AmberField> fields = _entityType.getFields(); 282 283 for (JMethod ctor : _entityType.getBeanClass().getConstructors()) { 284 out.println(); 285 out.print("public "); 287 288 out.print(className); 289 out.print("("); 290 291 JClass []args = ctor.getParameterTypes(); 292 for (int i = 0; i < args.length; i++) { 293 if (i != 0) 294 out.print(", "); 295 296 out.print(args[i].getPrintName()); 297 out.print(" a" + i); 298 } 299 out.println(")"); 300 out.println("{"); 301 out.pushDepth(); 302 303 out.print("super("); 304 for (int i = 0; i < args.length; i++) { 305 if (i != 0) 306 out.print(", "); 307 308 out.print("a" + i); 309 } 310 out.println(");"); 311 312 for (AmberField field : fields) { 313 field.generatePostConstructor(out); 314 } 315 316 out.popDepth(); 317 out.println("}"); 318 } 319 320 Id id = _entityType.getId(); 321 322 if (id == null) 323 throw new IllegalStateException (L.l("`{0}' is missing a key.", 324 _entityType.getName())); 325 326 if (id instanceof CompositeId) { 328 out.println(); 330 out.println("private " + id.getForeignTypeName() + " __caucho_compound_key = new " + id.getForeignTypeName() + "();"); 331 } 332 333 out.println(); 334 out.println("public void __caucho_setPrimaryKey(Object key)"); 335 out.println("{"); 336 out.pushDepth(); 337 338 id.generateSet(out, id.generateCastFromObject("key")); 339 340 out.popDepth(); 341 out.println("}"); 342 343 out.println(); 344 out.println("public Object __caucho_getPrimaryKey()"); 345 out.println("{"); 346 out.pushDepth(); 347 348 out.print("return "); 349 out.print(id.toObject(id.generateGetProperty("super"))); 350 out.println(";"); 351 352 out.popDepth(); 353 out.println("}"); 354 355 376 377 out.println(); 378 out.println("public void __caucho_setConnection(com.caucho.amber.manager.AmberConnection aConn)"); 379 out.println("{"); 380 out.pushDepth(); 381 382 out.println("__caucho_session = aConn;"); 383 384 out.popDepth(); 385 out.println("}"); 386 387 out.println(); 388 out.println("public com.caucho.amber.manager.AmberConnection __caucho_getConnection()"); 389 out.println("{"); 390 out.pushDepth(); 391 392 out.println("return __caucho_session;"); 393 394 out.popDepth(); 395 out.println("}"); 396 397 generateExpire(out); 398 } 399 400 403 private void generateExpire(JavaWriter out) 404 throws IOException 405 { 406 out.println(); 407 out.println("public void __caucho_expire()"); 408 out.println("{"); 409 410 int loadCount = _entityType.getLoadGroupIndex(); 411 for (int i = 0; i <= loadCount / 64; i++) { 412 out.println(" __caucho_loadMask_" + i + " = 0L;"); 413 } 414 415 _entityType.generateExpire(out); 416 417 out.println("}"); 418 } 419 420 423 private void generateMatch(JavaWriter out) 424 throws IOException 425 { 426 if (_entityType.getParentType() != null) 427 return; 428 429 out.println(); 430 out.println("public boolean __caucho_match(String className, Object key)"); 431 out.println("{"); 432 out.pushDepth(); 433 434 438 out.println("if (! (\"" + getBeanClassName() + "\".equals(className)))"); 439 out.println(" return false;"); 440 out.println("else {"); 441 out.pushDepth(); 442 443 out.println("try {"); 444 out.pushDepth(); 445 Id id = _entityType.getId(); 446 id.generateMatch(out, id.generateCastFromObject("key")); 447 out.popDepth(); 448 out.println("} catch (ClassCastException e) {"); 449 out.println(" throw new IllegalArgumentException(\"Primary key type is incorrect: '\"+key.getClass().getName()+\"'\");"); 450 out.println("}"); 451 452 out.popDepth(); 453 out.println("}"); 454 455 out.popDepth(); 456 out.println("}"); 457 } 458 459 462 private void generatePrologue(JavaWriter out, HashSet <Object > completedSet) 463 throws IOException 464 { 465 for (Column column : _entityType.getColumns()) { 466 column.generatePrologue(out); 467 } 468 469 Id id = _entityType.getId(); 470 471 if (id != null) 472 id.generatePrologue(out, completedSet); 473 474 ArrayList <AmberField> fields = _entityType.getFields(); 475 476 for (int i = 0; i < fields.size(); i++) { 477 AmberField prop = fields.get(i); 478 479 prop.generatePrologue(out, completedSet); 480 } 481 } 482 483 486 private void generateGetEntityType(JavaWriter out) 487 throws IOException 488 { 489 out.println(); 490 out.println("public com.caucho.amber.type.EntityType __caucho_getEntityType()"); 491 out.println("{"); 492 out.pushDepth(); 493 494 out.println("return __caucho_home;"); 495 496 out.popDepth(); 497 out.println("}"); 498 } 499 500 503 private void generateGetEntityState(JavaWriter out) 504 throws IOException 505 { 506 out.println(); 507 out.println("public int __caucho_getEntityState()"); 508 out.println("{"); 509 out.pushDepth(); 510 511 out.println("return __caucho_state;"); 512 513 out.popDepth(); 514 out.println("}"); 515 } 516 517 520 private void generateFields(JavaWriter out) 521 throws IOException 522 { 523 ArrayList <AmberField> fields = _entityType.getFields(); 524 525 for (int i = 0; i < fields.size(); i++) { 526 AmberField prop = fields.get(i); 527 528 prop.generateSuperGetter(out); 529 prop.generateGetProperty(out); 530 531 prop.generateSuperSetter(out); 532 prop.generateSetProperty(out); 533 } 534 } 535 536 539 private void generateMethods(JavaWriter out) 540 throws IOException 541 { 542 for (StubMethod method : _entityType.getMethods()) { 543 method.generate(out); 544 } 545 } 546 547 550 private void generateLoad(JavaWriter out) 551 throws IOException 552 { 553 557 if (_entityType.getParentType() == null) { 558 out.println(); 559 out.println("public boolean __caucho_makePersistent(com.caucho.amber.manager.AmberConnection aConn, com.caucho.amber.type.EntityType home)"); 560 out.println(" throws java.sql.SQLException"); 561 out.println("{"); 562 out.pushDepth(); 563 564 out.println("__caucho_session = aConn;"); 565 out.println("if (home != null)"); 566 out.println(" __caucho_home = home;"); 567 568 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_NON_TRANSACTIONAL;"); 569 570 int loadCount = _entityType.getLoadGroupIndex(); 571 for (int i = 0; i <= loadCount / 64; i++) { 572 out.println(" __caucho_loadMask_" + i + " = 0L;"); 573 } 574 575 int dirtyCount = _entityType.getDirtyIndex(); 576 for (int i = 0; i <= dirtyCount / 64; i++) { 577 out.println(" __caucho_dirtyMask_" + i + " = 0L;"); 578 out.println(" __caucho_updateMask_" + i + " = 0L;"); 579 } 580 581 out.println(); 582 out.println("return true;"); 583 584 out.popDepth(); 585 out.println("}"); 586 } 587 588 int index = _entityType.getLoadGroupIndex(); 589 590 boolean hasLoad = (_entityType.getFields().size() > 0); 591 592 if (_entityType.getParentType() == null) { 593 index = 0; 594 hasLoad = hasLoad || (_entityType.getId() != null); 595 } 596 597 out.println(); 598 out.println("public void __caucho_retrieve(com.caucho.amber.manager.AmberConnection aConn)"); 599 out.println(" throws java.sql.SQLException"); 600 out.println("{"); 601 602 if (hasLoad) 603 out.println(" __caucho_load_" + index + "(aConn);"); 604 605 out.println("}"); 606 607 out.println(); 608 out.println("public void __caucho_retrieve(com.caucho.amber.manager.AmberConnection aConn, java.util.Map preloadedProperties)"); 609 out.println(" throws java.sql.SQLException"); 610 out.println("{"); 611 612 if (hasLoad) 613 out.println(" __caucho_load_" + index + "(aConn, preloadedProperties);"); 614 615 out.println("}"); 616 } 617 618 621 private void generateDetach(JavaWriter out) 622 throws IOException 623 { 624 if (_entityType.getParentType() != null) 625 return; 626 627 out.println(); 628 out.println("public void __caucho_detach()"); 629 out.println("{"); 630 out.pushDepth(); 631 632 out.println("__caucho_session = null;"); 633 634 637 out.println("__caucho_state = com.caucho.amber.entity.Entity.TRANSIENT;"); 638 639 out.popDepth(); 640 out.println("}"); 641 } 642 643 646 private void generateLoadGroup(JavaWriter out, int groupIndex) 647 throws IOException 648 { 649 if (_entityType.hasLoadGroup(groupIndex)) { 650 new LoadGroupGenerator(_extClassName, _entityType, groupIndex).generate(out); 651 } 652 } 653 654 657 private void generateResultSetLoad(JavaWriter out) 658 throws IOException 659 { 660 if (_entityType.getParentType() != null) 661 return; 662 663 out.println(); 664 out.println("public int __caucho_load(com.caucho.amber.manager.AmberConnection aConn, java.sql.ResultSet rs, int index)"); 665 out.println(" throws java.sql.SQLException"); 666 out.println("{"); 667 out.pushDepth(); 668 669 int index = _entityType.generateLoad(out, "rs", "index", 0, 0); 670 671 out.println("__caucho_loadMask_0 |= 1L;"); 672 673 int dirtyCount = _entityType.getDirtyIndex(); 674 675 for (int i = 0; i <= dirtyCount / 64; i++) { 676 out.println("__caucho_dirtyMask_" + i + " = 0;"); 677 678 } 681 682 out.println(); 683 out.println("if (__caucho_state == com.caucho.amber.entity.Entity.P_TRANSACTIONAL || __caucho_state == com.caucho.amber.entity.Entity.P_NEW) {"); 684 out.println("}"); 685 out.println("else if (__caucho_session == null ||"); 686 out.println(" ! __caucho_session.isInTransaction()) {"); 687 out.println(" __caucho_state = com.caucho.amber.entity.Entity.P_NON_TRANSACTIONAL;"); 688 out.println(" if (__caucho_item != null)"); 689 out.println(" __caucho_item.save(this);"); 690 out.println("}"); 691 out.println("else {"); 692 out.println(" __caucho_state = com.caucho.amber.entity.Entity.P_TRANSACTIONAL;"); 693 out.println(" aConn.makeTransactional(this);"); 694 out.println("}"); 695 696 if (_entityType.getHasLoadCallback()) { 697 out.println(); 698 out.println("__caucho_load_callback();"); 699 } 700 701 out.println("return " + index + ";"); 702 out.popDepth(); 703 out.println("}"); 704 } 705 706 709 private void generateSetQuery(JavaWriter out) 710 throws IOException 711 { 712 if (_entityType.getParentType() != null) 713 return; 714 715 out.println(); 716 out.println("public void __caucho_setKey(java.sql.PreparedStatement pstmt, int index)"); 717 out.println(" throws java.sql.SQLException"); 718 out.println("{"); 719 out.pushDepth(); 720 721 _entityType.generateSet(out, "pstmt", "index", "super"); 722 723 out.popDepth(); 724 out.println("}"); 725 } 726 727 730 private void generateFlush(JavaWriter out) 731 throws IOException 732 { 733 out.println(); 734 out.println("public void __caucho_increment_version()"); 735 out.println("{"); 736 out.pushDepth(); 737 738 out.println("if (__caucho_inc_version)"); 739 out.println(" return;"); 740 out.println(); 741 out.println("__caucho_inc_version = true;"); 742 743 VersionField version = _entityType.getVersionField(); 744 745 if (version != null) 746 version.generateIncrementVersion(out); 747 748 out.popDepth(); 749 out.println("}"); 750 751 out.println(); 752 out.println("protected void __caucho_flush_callback()"); 753 out.println(" throws java.sql.SQLException"); 754 out.println("{"); 755 out.println("}"); 756 757 out.println(); 758 out.println("public boolean __caucho_flush()"); 759 out.println(" throws java.sql.SQLException"); 760 out.println("{"); 761 out.pushDepth(); 762 763 out.println("if (__caucho_session == null)"); 764 out.println(" return false;"); 765 out.println(); 766 767 ArrayList <AmberField> fields = _entityType.getFields(); 768 769 for (int i = 0; i < fields.size(); i++) { 770 AmberField field = fields.get(i); 771 772 if (field.isCascadable()) { 773 CascadableField cascadable = (CascadableField) field; 774 775 cascadable.generateFlushCheck(out); 776 777 out.println(); 778 } 779 } 780 781 out.println(); 782 out.println("if (__caucho_state == com.caucho.amber.entity.Entity.P_DELETED) {"); 783 out.println(" __caucho_delete_int();"); 784 out.println(" return true;"); 785 out.println("}"); 786 out.println(); 787 out.println("boolean isDirty = false;"); 788 789 int dirtyCount = _entityType.getDirtyIndex(); 790 791 for (int i = 0; i <= dirtyCount / 64; i++) { 792 out.println("long mask_" + i + " = __caucho_dirtyMask_" + i + ";"); 793 out.println("__caucho_dirtyMask_" + i + " = 0L;"); 794 out.println("__caucho_updateMask_" + i + " |= mask_" + i + ";"); 795 796 out.println(); 797 out.println("if (mask_" + i + " != 0L)"); 798 out.println(" isDirty = true;"); 799 } 800 801 out.println("__caucho_session.preUpdate(this);"); 802 803 generateCallbacks(out, "this", _entityType.getPreUpdateCallbacks()); 804 805 out.println(); 806 out.println("__caucho_flush_callback();"); 807 808 out.println(); 809 810 out.println("if (! isDirty)"); 812 out.println(" return true;"); 817 818 out.println("com.caucho.util.CharBuffer cb = new com.caucho.util.CharBuffer();"); 819 820 out.println("__caucho_home.generateUpdateSQLPrefix(cb);"); 821 822 out.println("boolean isFirst = true;"); 823 824 for (int i = 0; i <= dirtyCount / 64; i++) { 825 if (i != 0 || version == null) { 827 out.println("if (mask_" + i + " != 0L)"); 828 out.print(" "); 829 } 830 831 out.println("isFirst = __caucho_home.generateUpdateSQLComponent(cb, " + i + ", mask_" + i + ", isFirst);"); 832 } 833 out.println("__caucho_home.generateUpdateSQLSuffix(cb);"); 834 835 out.println("java.sql.PreparedStatement pstmt = __caucho_session.prepareStatement(cb.toString());"); 836 837 out.println("int index = 1;"); 838 839 for (int i = 0; i < fields.size(); i++) { 840 AmberField field = fields.get(i); 841 842 field.generateUpdate(out, "mask", "pstmt", "index"); 843 } 844 845 out.println(); 846 _entityType.getId().generateSet(out, "pstmt", "index"); 847 848 if (version != null) { 849 out.println(); 850 version.generateSet(out, "pstmt", "index"); 851 } 852 853 out.println(); 854 out.println("int updateCount = pstmt.executeUpdate();"); 855 out.println(); 856 857 if (version != null) { 858 out.println("if (updateCount == 0) {"); 859 out.println(" throw new javax.persistence.OptimisticLockException(this);"); 860 out.println("} else {"); 861 out.pushDepth(); 862 String value = version.generateGet("super"); 863 Type type = version.getColumn().getType(); 864 out.println(version.generateSuperSetter(type.generateIncrementVersion(value)) + ";"); 865 out.popDepth(); 866 out.println("}"); 867 out.println(); 868 } 869 870 out.println("__caucho_session.postUpdate(this);"); 871 872 generateCallbacks(out, "this", _entityType.getPostUpdateCallbacks()); 873 874 out.println(); 875 out.println("if (__caucho_log.isLoggable(java.util.logging.Level.FINE))"); 876 out.println(" __caucho_log.fine(\"amber update \" + this.getClass().getName() + \" - PK: \" + __caucho_getPrimaryKey());"); 877 878 out.println(); 879 out.println("__caucho_inc_version = false;"); 880 out.println(); 881 882 out.println("return false;"); 883 out.popDepth(); 884 out.println("}"); 885 } 886 887 890 private void generateFlushUpdate(JavaWriter out) 891 throws IOException 892 { 893 out.println(); 894 out.println("protected void __caucho_flushUpdate(long mask, com.caucho.amber.type.EntityType home)"); 895 out.println(" throws java.sql.SQLException"); 896 out.println("{"); 897 out.pushDepth(); 898 899 if (_entityType.getParentType() != null) { 900 out.println("super.__caucho_flushUpdate(mask, home.getParentType());"); 901 } 902 903 EntityType type = _entityType; 904 905 out.println("String sql = home.generateUpdateSQL(mask);"); 906 907 out.println("if (sql != null) {"); 908 out.pushDepth(); 909 910 out.println("java.sql.PreparedStatement pstmt = __caucho_session.prepareStatement(sql);"); 911 912 out.println("int index = 1;"); 913 914 ArrayList <AmberField> fields = _entityType.getFields(); 915 for (int i = 0; i < fields.size(); i++) { 916 AmberField field = fields.get(i); 917 918 field.generateUpdate(out, "mask", "pstmt", "index"); 919 } 920 921 out.println(); 922 _entityType.getId().generateSet(out, "pstmt", "index"); 923 924 out.println(); 925 out.println("pstmt.executeUpdate();"); 926 927 out.println(); 928 out.println("if (__caucho_log.isLoggable(java.util.logging.Level.FINE))"); 929 out.println(" __caucho_log.fine(\"amber update \" + this.getClass().getName() + \" - PK: \" + __caucho_getPrimaryKey());"); 930 931 934 out.popDepth(); 935 out.println("}"); 936 937 out.popDepth(); 938 out.println("}"); 939 } 940 941 944 private void generateAfterCommit(JavaWriter out) 945 throws IOException 946 { 947 958 out.println(); 959 out.println("public void __caucho_afterCommit()"); 960 out.println("{"); 961 out.pushDepth(); 962 963 out.println("int state = __caucho_state;"); 964 int dirtyCount = _entityType.getDirtyIndex(); 965 for (int i = 0; i <= dirtyCount / 64; i++) { 966 out.println("long updateMask_" + i + " = __caucho_updateMask_" + i + ";"); 967 } 968 969 976 out.println(); 977 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_NON_TRANSACTIONAL;"); 978 979 for (int i = 0; i <= dirtyCount / 64; i++) { 980 out.println("__caucho_updateMask_" + i + " = 0L;"); 981 } 982 983 out.print("if (updateMask_0 != 0L"); 984 for (int i = 1; i <= dirtyCount / 64; i++) 985 out.print(" || updateMask_" + i + " != 0L"); 986 out.println(")"); 987 out.println(" __caucho_session.update(this);"); 988 989 out.println("if (__caucho_item != null) {"); 990 out.pushDepth(); 991 992 out.println(_extClassName + " item = (" + _extClassName + ") __caucho_item.getEntity();"); 993 994 if (_entityType.getParentType() != null) { 995 out.println("if ((__caucho_loadMask_0 & 1L) != 0) {"); 998 out.pushDepth(); 999 out.println("item.__caucho_loadMask_0 = 1L;"); 1000 1001 _entityType.generateCopyLoadObject(out, "item", "super", 0); 1002 } 1003 1004 for (int i = 1; i <= _entityType.getLoadGroupIndex(); i++) { 1005 String loadVar = "__caucho_loadMask_" + (i / 64); 1006 long mask = (1L << (i % 64)); 1007 1008 out.println("if ((" + loadVar + " & " + mask + "L) != 0) {"); 1010 out.pushDepth(); 1011 1012 _entityType.generateCopyLoadObject(out, "item", "super", i); 1013 1014 out.println("item." + loadVar + " |= " + mask + "L;"); 1015 1016 out.popDepth(); 1017 out.println("}"); 1018 } 1020 1021 if (_entityType.getParentType() != null) { 1022 out.popDepth(); 1023 out.println("}"); 1024 } 1025 1026 for (int i = 0; i < _entityType.getDirtyIndex(); i++) { 1027 int group = i / 64; 1028 long mask = (1L << (i % 64)); 1029 1030 if (_entityType.isDirtyIndexOwnedByType(i)) { 1031 out.println("if ((updateMask_" + group + " & " + mask + "L) != 0) {"); 1032 out.pushDepth(); 1033 1034 _entityType.generateCopyUpdateObject(out, "item", "super", i); 1035 1036 out.popDepth(); 1037 out.println("}"); 1038 } 1039 } 1040 1041 out.popDepth(); 1042 out.println("}"); 1043 1044 out.popDepth(); 1045 out.println("}"); 1046 } 1047 1048 1051 private void generateAfterRollback(JavaWriter out) 1052 throws IOException 1053 { 1054 out.println(); 1055 out.println("public void __caucho_afterRollback()"); 1056 out.println("{"); 1057 out.pushDepth(); 1058 1059 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_NON_TRANSACTIONAL;"); 1060 1061 int loadCount = _entityType.getLoadGroupIndex(); 1062 for (int i = 0; i <= loadCount / 64; i++) { 1063 out.println("__caucho_loadMask_" + i + " = 0L;"); 1064 } 1065 1066 int dirtyCount = _entityType.getDirtyIndex(); 1067 for (int i = 0; i <= dirtyCount / 64; i++) { 1068 out.println("__caucho_dirtyMask_" + i + " = 0L;"); 1069 } 1070 1071 out.popDepth(); 1072 out.println("}"); 1073 } 1074 1075 private String getDebug() 1076 { 1077 return "this"; 1078 } 1079 1080 1083 private void generateCreate(JavaWriter out) 1084 throws IOException 1085 { 1086 ArrayList <IdField> fields = _entityType.getId().getKeys(); 1087 IdField idField = fields.size() > 0 ? fields.get(0) : null; 1088 1089 boolean hasReturnGeneratedKeys = false; 1090 1091 try { 1092 hasReturnGeneratedKeys = _entityType.getPersistenceUnit().hasReturnGeneratedKeys(); 1093 } catch (Exception e) { 1094 } 1098 1099 if (! hasReturnGeneratedKeys && 1100 idField != null && idField.getType().isAutoIncrement()) { 1101 out.println(); 1102 out.println("private static com.caucho.amber.field.Generator __caucho_id_gen;"); 1103 out.println("static {"); 1104 out.pushDepth(); 1105 out.println("com.caucho.amber.field.MaxGenerator gen = new com.caucho.amber.field.MaxGenerator();"); 1106 out.println("gen.setColumn(\"" + idField.getColumns().get(0).generateInsertName() + "\");"); 1107 out.println("gen.setTable(\"" + _entityType.getName() + "\");"); 1108 out.println("gen.init();"); 1109 out.popDepth(); 1110 out.println("}"); 1111 } 1112 1113 out.println(); 1114 out.println("public boolean __caucho_create(com.caucho.amber.manager.AmberConnection aConn, com.caucho.amber.type.EntityType home)"); 1115 out.println(" throws java.sql.SQLException"); 1116 out.println("{"); 1117 out.pushDepth(); 1118 1119 out.println("if (__caucho_session != null)"); 1120 out.println(" return true;"); 1121 1122 1125 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_NEW;"); 1126 1127 int loadCount = _entityType.getLoadGroupIndex(); 1128 for (int i = 0; i <= loadCount / 64; i++) { 1129 out.println("__caucho_loadMask_" + i + " = " + _entityType.getCreateLoadMask(i) + ";"); 1130 } 1131 1132 out.println("aConn.prePersist(this);"); 1133 1134 for (JMethod method : _entityType.getPrePersistCallbacks()) { 1135 out.println(method.getName() + "();"); 1136 } 1137 1138 int dirtyCount = _entityType.getDirtyIndex(); 1139 for (int i = 0; i <= dirtyCount / 64; i++) { 1140 out.println("__caucho_dirtyMask_" + i + " = 0L;"); 1141 } 1142 1143 Table table = _entityType.getTable(); 1144 1145 out.print("String sql = \""); 1146 out.print(_entityType.generateCreateSQL(table)); 1147 out.println("\";"); 1148 1149 _entityType.getId().generateCheckCreateKey(out); 1150 1151 out.println("java.sql.PreparedStatement pstmt = aConn.prepareInsertStatement(sql);"); 1152 1153 out.println("int index = 1;"); 1154 1155 out.println(); 1156 _entityType.getId().generateSetInsert(out, "pstmt", "index"); 1157 1158 _entityType.generateInsertSet(out, table, "pstmt", "index", "super"); 1159 1160 out.println(); 1161 out.println("pstmt.executeUpdate();"); 1162 1163 out.println(); 1164 _entityType.getId().generateSetGeneratedKeys(out, "pstmt"); 1165 1166 RelatedType parentType = _entityType; 1167 1168 do { 1169 for (Table subTable : parentType.getSecondaryTables()) { 1170 out.println(); 1171 out.print("sql = \""); 1172 out.print(parentType.generateCreateSQL(subTable)); 1173 out.println("\";"); 1174 1175 out.println("pstmt = aConn.prepareStatement(sql);"); 1176 1177 out.println("index = 1;"); 1178 1179 out.println(); 1180 parentType.getId().generateSetInsert(out, "pstmt", "index"); 1181 1182 parentType.generateInsertSet(out, subTable, "pstmt", "index", "super"); 1183 1184 out.println(); 1185 out.println("pstmt.executeUpdate();"); 1186 1187 out.println(); 1188 parentType.getId().generateSetGeneratedKeys(out, "pstmt"); 1189 } 1190 } 1191 while ((parentType = parentType.getParentType()) != null); 1192 1193 out.println(); 1194 out.println("__caucho_session = aConn;"); 1195 out.println("__caucho_home = home;"); 1196 1197 1199 out.println("__caucho_item = new com.caucho.amber.entity.CacheableEntityItem(home.getHome(), new " + getClassName() + "());"); 1200 out.println(getClassName() + " entity = (" + getClassName() + ") __caucho_item.getEntity();"); 1201 out.println("entity.__caucho_home = home;"); 1202 1203 ArrayList <IdField> keys = _entityType.getId().getKeys(); 1204 for (IdField key : keys) { 1205 String value = key.generateGet("super"); 1206 1207 out.println(key.generateSet("entity", value) + ";"); 1208 } 1209 1210 for (int i = 0; i < 1; i++) { 1211 _entityType.generateCopyUpdateObject(out, "entity", "super", i); 1212 } 1213 1214 for (int i = 0; i <= loadCount / 64; i++) { 1215 out.print("entity.__caucho_loadMask_" + i + " = "); 1216 out.println(_entityType.getCreateLoadMask(i) + ";"); 1217 } 1218 1219 out.println(); 1220 out.println("if (__caucho_log.isLoggable(java.util.logging.Level.FINE))"); 1221 out.println(" __caucho_log.fine(\"amber create \" + this.getClass().getName() + \" - PK: \" + __caucho_getPrimaryKey());"); 1222 out.println(); 1223 out.println("if (aConn.isInTransaction()) {"); 1224 out.println(" __caucho_state = com.caucho.amber.entity.Entity.P_TRANSACTIONAL;"); 1225 out.println(" aConn.makeTransactional(this);"); 1226 out.println("}"); 1227 out.println(); 1228 1229 out.println("aConn.postPersist(this);"); 1230 1231 for (JMethod method : _entityType.getPostPersistCallbacks()) { 1232 out.println(method.getName() + "();"); 1233 } 1234 1235 out.println(); 1236 out.println("return false;"); 1237 1238 out.popDepth(); 1239 out.println("}"); 1240 } 1241 1242 1245 private void generateDelete(JavaWriter out) 1246 throws IOException 1247 { 1248 out.println(); 1249 out.println("public void __caucho_delete()"); 1250 out.println("{"); 1251 out.pushDepth(); 1252 1253 out.println("if (__caucho_state >= com.caucho.amber.entity.Entity.P_DELETING)"); 1254 out.println(" return;"); 1255 out.println(); 1256 1257 out.println("if (__caucho_session != null)"); 1258 out.println(" __caucho_session.preRemove(this);"); 1259 out.println(); 1260 1261 generateCallbacks(out, "this", _entityType.getPreRemoveCallbacks()); 1262 1263 _entityType.generatePreDelete(out); 1264 1265 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_DELETING;"); 1266 1267 out.println("if (__caucho_session != null) {"); 1268 out.pushDepth(); 1269 out.println("__caucho_session.update(this);"); 1270 out.println("__caucho_home.getTable().beforeEntityDelete(__caucho_session, this);"); 1271 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_DELETED;"); 1272 _entityType.generatePostDelete(out); 1273 out.popDepth(); 1274 out.println("}"); 1275 out.println("else"); 1276 out.println(" __caucho_state = com.caucho.amber.entity.Entity.P_DELETED;"); 1277 1278 out.popDepth(); 1279 out.println("}"); 1280 1281 Id id = _entityType.getId(); 1282 1283 out.println(); 1284 out.println("private void __caucho_delete_int()"); 1285 out.println(" throws java.sql.SQLException"); 1286 out.println("{"); 1287 out.pushDepth(); 1288 1289 out.print("__caucho_home.delete(__caucho_session, "); 1290 out.print(id.toObject(id.generateGetProperty("this"))); 1291 out.println(");"); 1292 1293 out.println("__caucho_session.removeEntity(this);"); 1294 1295 String table = _entityType.getTable().getName(); 1296 String where = _entityType.getId().generateMatchArgWhere(null); 1297 1298 String sql = "delete from " + table + " where " + where; 1299 1300 out.println("String sql = \"" + sql + "\";"); 1301 1302 out.println(); 1303 out.println("java.sql.PreparedStatement pstmt = __caucho_session.prepareStatement(sql);"); 1304 1305 out.println("int index = 1;"); 1306 id.generateSet(out, "pstmt", "index", "this"); 1307 1308 out.println(); 1309 out.println("pstmt.executeUpdate();"); 1310 1311 out.println("__caucho_session.postRemove(this);"); 1312 1313 generateCallbacks(out, "this", _entityType.getPostRemoveCallbacks()); 1314 1315 out.popDepth(); 1316 out.println("}"); 1317 } 1318 1319 1322 private void generateDeleteForeign(JavaWriter out) 1323 throws IOException 1324 { 1325 out.println(); 1326 out.println("public void __caucho_invalidate_foreign(String table, Object key)"); 1327 out.println("{"); 1328 out.pushDepth(); 1329 1330 _entityType.generateInvalidateForeign(out); 1331 1332 out.popDepth(); 1333 out.println("}"); 1334 } 1335 1336 1337 1340 private void generateLoadFromObject(JavaWriter out) 1341 throws IOException 1342 { 1343 out.println(); 1344 out.println("public void __caucho_loadFromObject(Object src)"); 1345 out.println("{"); 1346 out.pushDepth(); 1347 1348 out.println(getClassName() + " o = (" + getClassName() + ") src;"); 1349 1350 if (_entityType.getParentType() != null) 1351 out.println("super.__caucho_loadFromObject(src);"); 1352 else { 1353 int loadCount = _entityType.getLoadGroupIndex(); 1354 for (int i = 0; i <= loadCount / 64; i++) { 1355 out.println("__caucho_loadMask_" + i + " = o.__caucho_loadMask_" + i + ";"); 1356 } 1357 } 1358 1359 int dirtyCount = _entityType.getDirtyIndex(); 1360 for (int i = 0; i <= dirtyCount / 64; i++) { 1361 out.println("__caucho_dirtyMask_" + i + " = 0;"); 1362 } 1363 1364 _entityType.generateLoadFromObject(out, "o"); 1365 1366 1373 1374 out.popDepth(); 1375 out.println("}"); 1376 } 1377 1378 1381 1402 1403 1406 private void generateCopy(JavaWriter out) 1407 throws IOException 1408 { 1409 out.println(); 1410 out.println("public com.caucho.amber.entity.Entity __caucho_copy(com.caucho.amber.manager.AmberConnection aConn,"); 1411 out.println(" com.caucho.amber.entity.EntityItem item)"); 1412 out.println("{"); 1413 out.pushDepth(); 1414 1415 out.println(getClassName() + " o = new " + getClassName() + "();"); 1416 1417 out.println("o.__caucho_home = __caucho_home;"); 1418 out.println("o.__caucho_item = item;"); 1419 1420 ArrayList <IdField> keys = _entityType.getId().getKeys(); 1421 1422 for (int i = 0; i < keys.size(); i++) { 1423 IdField key = keys.get(i); 1424 1425 out.println(key.generateSet("o", key.generateGet("super")) + ";"); 1426 } 1427 1428 for (int i = 0; i <= _entityType.getLoadGroupIndex(); i++) { 1429 _entityType.generateCopyLoadObject(out, "o", "super", i); 1431 } 1432 1433 out.println("o.__caucho_session = aConn;"); 1434 out.println("o.__caucho_state = __caucho_state;"); 1436 for (int i = 0; i <= _entityType.getLoadGroupIndex() / 64; i++) { 1437 String mask = "__caucho_loadMask_" + i; 1438 1439 out.println("o." + mask + " = " + mask + ";"); 1440 } 1441 1442 int dirtyCount = _entityType.getDirtyIndex(); 1443 1444 for (int i = 0; i <= dirtyCount / 64; i++) { 1446 String mask = "__caucho_dirtyMask_" + i; 1447 1448 out.println("o." + mask + " = 0L;"); 1449 } 1450 1451 1457 out.println(); 1458 out.println("return o;"); 1459 1460 out.popDepth(); 1461 out.println("}"); 1462 } 1463 1464 1467 private void generateMakePersistent(JavaWriter out) 1468 throws IOException 1469 { 1470 out.println(); 1471 out.println("public void __caucho_makePersistent(com.caucho.amber.manager.AmberConnection aConn,"); 1472 out.println(" com.caucho.amber.entity.EntityItem item)"); 1473 out.println("{"); 1474 out.pushDepth(); 1475 1476 out.println(_extClassName + " entity = (" + _extClassName + ") item.getEntity();"); 1477 1478 out.println("__caucho_home = entity.__caucho_home;"); 1479 out.println("if (__caucho_home == null) throw new NullPointerException();"); 1480 out.println("__caucho_item = item;"); 1481 1482 ArrayList <IdField> keys = _entityType.getId().getKeys(); 1483 1484 for (int i = 0; i < keys.size(); i++) { 1485 IdField key = keys.get(i); 1486 1487 out.println(key.generateSet("super", key.generateGet("entity")) + ";"); 1488 } 1489 1490 out.println("__caucho_session = aConn;"); 1491 1492 out.println("__caucho_state = com.caucho.amber.entity.Entity.P_NON_TRANSACTIONAL;"); 1494 1496 out.popDepth(); 1497 out.println("}"); 1498 } 1499 1500 1503 private void generateCascadePersist(JavaWriter out) 1504 throws IOException 1505 { 1506 out.println(); 1507 out.println("public void __caucho_cascadePrePersist(com.caucho.amber.manager.AmberConnection aConn)"); 1508 out.println(" throws java.sql.SQLException"); 1509 out.println("{"); 1510 out.pushDepth(); 1511 1512 1515 ArrayList <AmberField> fields = _entityType.getFields(); 1516 1517 for (int i = 0; i < fields.size(); i++) { 1518 AmberField field = fields.get(i); 1519 1520 if (field.isCascadable()) { 1521 CascadableField cascadable = (CascadableField) field; 1522 1523 out.println(); 1524 1525 cascadable.generatePreCascade(out, "aConn", CascadeType.PERSIST); 1526 } 1527 } 1528 1529 out.popDepth(); 1530 out.println("}"); 1531 1532 out.println(); 1533 out.println("public void __caucho_cascadePostPersist(com.caucho.amber.manager.AmberConnection aConn)"); 1534 out.println(" throws java.sql.SQLException"); 1535 out.println("{"); 1536 out.pushDepth(); 1537 1538 for (int i = 0; i < fields.size(); i++) { 1539 AmberField field = fields.get(i); 1540 1541 if (field.isCascadable()) { 1542 CascadableField cascadable = (CascadableField) field; 1543 1544 out.println(); 1545 1546 cascadable.generatePostCascade(out, "aConn", CascadeType.PERSIST); 1547 } 1548 } 1549 1550 out.popDepth(); 1551 out.println("}"); 1552 } 1553 1554 1557 private void generateCascadeRemove(JavaWriter out) 1558 throws IOException 1559 { 1560 out.println(); 1561 out.println("public void __caucho_cascadePreRemove(com.caucho.amber.manager.AmberConnection aConn)"); 1562 out.println(" throws java.sql.SQLException"); 1563 out.println("{"); 1564 out.pushDepth(); 1565 1566 ArrayList <AmberField> fields = _entityType.getFields(); 1567 1568 for (int i = 0; i < fields.size(); i++) { 1569 AmberField field = fields.get(i); 1570 1571 if (field.isCascadable()) { 1572 CascadableField cascadable = (CascadableField) field; 1573 1574 out.println(); 1575 1576 cascadable.generatePreCascade(out, "aConn", CascadeType.REMOVE); 1577 } 1578 } 1579 1580 out.popDepth(); 1581 out.println("}"); 1582 1583 out.println(); 1584 out.println("public void __caucho_cascadePostRemove(com.caucho.amber.manager.AmberConnection aConn)"); 1585 out.println(" throws java.sql.SQLException"); 1586 out.println("{"); 1587 out.pushDepth(); 1588 1589 for (int i = 0; i < fields.size(); i++) { 1590 AmberField field = fields.get(i); 1591 1592 if (field.isCascadable()) { 1593 CascadableField cascadable = (CascadableField) field; 1594 1595 out.println(); 1596 1597 cascadable.generatePostCascade(out, "aConn", CascadeType.REMOVE); 1598 } 1599 } 1600 1601 out.popDepth(); 1602 out.println("}"); 1603 } 1604 1605 1608 private void generateHome(JavaWriter out) 1609 throws IOException 1610 { 1611 generateHomeFind(out); 1612 1613 if (! (_entityType instanceof SubEntityType)) { 1614 generateHomeNew(out); 1615 } 1616 } 1617 1618 1621 private void generateHomeFind(JavaWriter out) 1622 throws IOException 1623 { 1624 out.println(); 1625 out.print("public com.caucho.amber.entity.EntityItem __caucho_home_find("); 1626 out.print("com.caucho.amber.manager.AmberConnection aConn,"); 1627 out.print("com.caucho.amber.entity.AmberEntityHome home,"); 1628 out.println("java.sql.ResultSet rs, int index)"); 1629 out.println(" throws java.sql.SQLException"); 1630 out.println("{"); 1631 out.pushDepth(); 1632 1633 1634 out.print("Object key = "); 1635 int index = _entityType.getId().generateLoadForeign(out, "rs", "index", 0); 1636 out.println(";"); 1637 1638 if (_entityType.getDiscriminator() == null) { 1639 out.println("return home.findEntityItem(aConn, key, false);"); 1640 } 1641 else { 1642 out.println("String discriminator = rs.getString(index + " + index + ");"); 1643 out.println(); 1644 out.println("return home.findDiscriminatorEntityItem(aConn, key, discriminator);"); 1645 } 1646 1647 out.popDepth(); 1648 out.println("}"); 1649 } 1650 1651 1654 private void generateHomeNew(JavaWriter out) 1655 throws IOException 1656 { 1657 out.println(); 1658 out.print("public com.caucho.amber.entity.Entity __caucho_home_new("); 1659 out.print("com.caucho.amber.manager.AmberConnection aConn,"); 1660 out.print("com.caucho.amber.entity.AmberEntityHome home,"); 1661 out.print("Object key)"); 1662 out.println(" throws java.sql.SQLException"); 1663 out.println("{"); 1664 out.println(" return __caucho_home_new(aConn, home, key, true);"); 1665 out.println("}"); 1666 1667 out.println(); 1668 out.print("public com.caucho.amber.entity.Entity __caucho_home_new("); 1669 out.print("com.caucho.amber.manager.AmberConnection aConn,"); 1670 out.print("com.caucho.amber.entity.AmberEntityHome home,"); 1671 out.print("Object key,"); 1672 out.print("boolean loadFromResultSet)"); 1673 out.println(" throws java.sql.SQLException"); 1674 out.println("{"); 1675 out.pushDepth(); 1676 1677 Column discriminator = _entityType.getDiscriminator(); 1678 1679 if (discriminator == null) { 1680 out.println(getClassName() + " entity = new " + getClassName() + "();"); 1681 1682 out.println("entity.__caucho_home = home.getEntityType();"); 1683 out.println("entity.__caucho_setPrimaryKey(key);"); 1684 1685 out.println("return entity;"); 1686 } 1687 else { 1688 1689 String rootTableName = _entityType.getRootTableName(); 1690 1691 generateHomeNewLoading(out, rootTableName); 1692 1693 out.println("com.caucho.amber.entity.EntityItem item = home.findDiscriminatorEntityItem(aConn, key, rs" + rootTableName + ".getString(1));"); 1694 1695 out.println("if (loadFromResultSet) {"); 1697 out.pushDepth(); 1698 1699 1701 out.println("item.getEntity().__caucho_load(aConn, rs" + rootTableName + ", 1);"); 1702 1703 out.popDepth(); 1704 out.println("}"); 1705 1706 out.println(getClassName() + " entity = (" + getClassName() + ") item.copy(aConn);"); 1707 1708 out.println("rs" + rootTableName + ".close();"); 1709 out.println("return entity;"); 1710 } 1711 1712 out.popDepth(); 1713 out.println("}"); 1714 } 1715 1716 1719 private void generateHomeNewLoading(JavaWriter out, 1720 String rootTableName) 1721 throws IOException 1722 { 1723 String varSuffix = rootTableName == null ? "" : rootTableName; 1724 1725 out.print("String sql" + varSuffix + " = \"select "); 1726 out.print(_entityType.generateLoadSelect("o")); 1727 out.print(" from "); 1728 1729 if (rootTableName == null) 1730 out.print(_entityType.getTable().getName()); 1731 else 1732 out.print(rootTableName); 1733 1734 out.print(" o where "); 1735 out.print(_entityType.getId().generateMatchArgWhere("o")); 1736 out.println("\";"); 1737 1738 out.println("java.sql.PreparedStatement pstmt" + varSuffix + " = aConn.prepareStatement(sql" + varSuffix + ");"); 1739 1740 String keyType = _entityType.getId().getForeignTypeName(); 1741 1742 out.println(keyType + " " + "keyValue" + varSuffix + " = (" + keyType + ") key;"); 1743 1744 out.println("int index" + varSuffix + " = 1;"); 1745 _entityType.getId().generateSetKey(out, "pstmt"+varSuffix, 1746 "index"+varSuffix, "keyValue"+varSuffix); 1747 1748 out.println("java.sql.ResultSet rs" + varSuffix + " = pstmt" + varSuffix + ".executeQuery();"); 1749 out.println("if (! rs" + varSuffix + ".next()) {"); 1750 out.println(" rs" + varSuffix + ".close();"); 1751 out.println(" return null;"); 1752 out.println("}"); 1754 } 1755 1756 private void generateCallbacks(JavaWriter out, 1757 String object, 1758 ArrayList <JMethod> callbacks) 1759 throws IOException 1760 { 1761 if (callbacks.size() > 0) { 1762 1763 out.println(); 1764 1765 for (JMethod method : callbacks) { 1766 out.println(object + "." + method.getName() + "();"); 1767 } 1768 } 1769 } 1770 1771 private void generateInternals(JavaWriter out) 1772 throws IOException 1773 { 1774 out.println(); 1775 out.println("private void __caucho_setInternalString(java.sql.PreparedStatement pstmt, int index, String s)"); 1776 out.println(" throws java.sql.SQLException"); 1777 out.println("{"); 1778 out.pushDepth(); 1779 out.println("if (s == null)"); 1780 out.println(" pstmt.setNull(index, java.sql.Types.NULL);"); 1781 out.println("else"); 1782 out.println(" pstmt.setString(index, s);"); 1783 out.popDepth(); 1784 out.println("}"); 1785 } 1786} 1787 | Popular Tags |