private boolean addSerializeMethods(CtClass cc, boolean callSuper) throws NotFoundException, CannotCompileException { CtField[] fields = cc.getDeclaredFields(); int size = 0; StringBuffer sb = new StringBuffer(); sb.append(callSuper ? "{$2=super.pack($1, $2);$1.extend($2" : "{$1.extend($2"); for (int i = 0; i < fields.length; i++) { CtField f = fields[i]; if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) { CtClass type = f.getType(); if (type.isPrimitive()) { if (type == CtClass.booleanType || type == CtClass.byteType) { size += 1; } else if (type == CtClass.charType || type == CtClass.shortType) { size += 2; } else if (type == CtClass.longType || type == CtClass.doubleType) { size += 8; } else { size += 4; } } else if (type.getName().equals("java.lang.String")) { sb.append("+org.nachodb.impl.Bytes#sizeof("); sb.append(f.getName()); sb.append(",$3)"); } else { return false; } } } cc.addInterface(serializable); CtMethod m = new CtMethod(pack, cc, null); sb.append('+'); sb.append(size); sb.append(");"); for (int i = 0; i < fields.length; i++) { CtField f = fields[i]; if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) { CtClass type = f.getType(); String name = f.getName(); if (type == CtClass.booleanType) { sb.append("$1.arr[$2++]=(byte)("); sb.append(name); sb.append("?1:0);"); } else if (type == CtClass.charType) { sb.append("org.nachodb.impl.Bytes#pack2($1.arr,$2,(short)"); sb.append(name); sb.append(");$2+=2;"); } else if (type == CtClass.byteType) { sb.append("$1.arr[$2++]="); sb.append(name); sb.append(";"); } else if (type == CtClass.shortType) { sb.append("org.nachodb.impl.Bytes#pack2($1.arr,$2,"); sb.append(name); sb.append(");$2+=2;"); } else if (type == CtClass.intType) { sb.append("org.nachodb.impl.Bytes#pack4($1.arr,$2,"); sb.append(name); sb.append(");$2+=4;"); } else if (type == CtClass.longType) { sb.append("org.nachodb.impl.Bytes#pack8($1.arr,$2,"); sb.append(name); sb.append(");$2+=8;"); } else if (type == CtClass.doubleType) { sb.append("org.nachodb.impl.Bytes#packF8($1.arr,$2,"); sb.append(name); sb.append(");$2+=8;"); } else if (type == CtClass.floatType) { sb.append("org.nachodb.impl.Bytes#packF4($1.arr,$2,"); sb.append(name); sb.append(");$2+=4;"); } else { sb.append("$2=org.nachodb.impl.Bytes#packStr($1.arr,$2,"); sb.append(name); sb.append(",$3);"); } } } sb.append("return $2;}"); m.setBody(sb.toString()); cc.addMethod(m); m = new CtMethod(unpack, cc, null); sb = new StringBuffer(); sb.append(callSuper ? "{$2=super.unpack($1, $2);" : "{"); for (int i = 0; i < fields.length; i++) { CtField f = fields[i]; if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) { CtClass type = f.getType(); String name = f.getName(); sb.append(name); sb.append('='); if (type == CtClass.booleanType) { sb.append("$1[$2++]!=0;"); } else if (type == CtClass.charType) { sb.append("(char)org.nachodb.impl.Bytes#unpack2($1,$2);$2+=2;"); } else if (type == CtClass.byteType) { sb.append("$1[$2++];"); } else if (type == CtClass.shortType) { sb.append("org.nachodb.impl.Bytes#unpack2($1,$2);$2+=2;"); } else if (type == CtClass.intType) { sb.append("org.nachodb.impl.Bytes#unpack4($1,$2);$2+=4;"); } else if (type == CtClass.longType) { sb.append("org.nachodb.impl.Bytes#unpack8($1,$2);$2+=8;"); } else if (type == CtClass.doubleType) { sb.append("org.nachodb.impl.Bytes#unpackF8($1,$2);$2+=8;"); } else if (type == CtClass.floatType) { sb.append("org.nachodb.impl.Bytes#unpackF4($1,$2);$2+=4;"); } else { sb.append( "org.nachodb.impl.Bytes#unpackStr($1,$2,$3);$2+=org.nachodb.impl.Bytes#sizeof($1,$2);"); } } } sb.append("return $2;}"); m.setBody(sb.toString()); cc.addMethod(m); return true; }
/* Hibernate 的关联关系太复杂了。要么你区分控制端和被控制端。要么你必须在使用的时候将两端都设置好关联关系。 对于mappedBy也是一个无语的设计。为什么我要通过它来区分控制端? */ @Override public void enhance(CtClass ctClass) throws Exception { CtField[] fields = ctClass.getDeclaredFields(); // String entityListener = "javax.persistence.EntityListeners"; // if (ctClass.hasAnnotation(EntityCallback.class)) { // EntityCallback entityListeners = (EntityCallback) // ctClass.getAnnotation(EntityCallback.class); // String clzzName = entityListeners.value(); // CtClass clzz = ServiceFramwork.classPool.get(clzzName); // enhanceJPACallback(clzz); // AnnotationsAttribute annotationsAttribute = // EnhancerHelper.getAnnotations(ctClass); // ArrayMemberValue arrayMemberValue = new // ArrayMemberValue(annotationsAttribute.getConstPool()); // ClassMemberValue[] clzzes = new ClassMemberValue[]{new ClassMemberValue(clzzName, // annotationsAttribute.getConstPool())}; // arrayMemberValue.setValue(clzzes); // EnhancerHelper.createAnnotation(annotationsAttribute, EntityListeners.class, // map("value", arrayMemberValue)); // // } else { // // } enhanceJPACallback(ctClass); for (CtField ctField : fields) { if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.OneToOne")) { DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class); Map<String, String> columns = dbInfo.tableColumns.get(ctClass.getSimpleName()); String clzzName = findAssociatedClassName(ctField); CtField mappedByField = findAssociatedField(ctClass, clzzName); if (!columns.containsKey(ctField.getName() + "_id")) { setMappedBy(ctField, mappedByField.getName(), "OneToOne"); } else { setMappedBy(mappedByField, mappedByField.getName(), "OneToOne"); } setCascad(mappedByField, "OneToOne"); setCascad(ctField, "OneToOne"); String mappedByClassName = clzzName; String mappedByFieldName = mappedByField.getName(); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.OneToOne"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.attr(\"{}\",obj);" + " obj.attr(\"{}\",this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), mappedByClassName, ctField.getName(), mappedByFieldName), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.OneToMany")) { String clzzName = findAssociatedClassName(ctField); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); // 如果没有设置mappedBy我们帮他设置吧 setMappedBy(ctField, mappedByFieldName, "OneToMany"); setCascad(ctField, "OneToMany"); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "set" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.OneToMany"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.{}.add(obj);" + " obj.{}(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.ManyToOne")) { String clzzName = ctField.getType().getName(); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); // 默认设置为cascade = CascadeType.PERSIST setCascad(ctField, "ManyToOne"); findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "get" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.ManyToOne"), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " this.{} = obj;" + " obj.{}().add(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } if (EnhancerHelper.hasAnnotation(ctField, "javax.persistence.ManyToMany")) { String clzzName = findAssociatedClassName(ctField); String mappedByFieldName = findAssociatedFieldName(ctClass, clzzName); String mappedByClassName = ctClass.getName(); CtField other = findAssociatedField(ctClass, clzzName); DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class); String otherClassSimpleName = findAssociatedClass(ctClass.getClassPool(), ctField).getSimpleName(); String maybeTable1 = ctClass.getSimpleName() + "_" + otherClassSimpleName; String maybeTable2 = otherClassSimpleName + "_" + ctClass.getSimpleName(); String finalTableName = dbInfo.tableNames.contains(maybeTable1) ? maybeTable1 : maybeTable2; setCascad(ctField, "ManyToMany"); boolean isMaster = false; if (!ctField.hasAnnotation(ManyToManyHint.class)) { if (dbInfo.tableNames.contains(maybeTable1)) { setMappedBy(other, ctField.getName(), "ManyToMany"); isMaster = true; finalTableName = maybeTable1; } if (dbInfo.tableNames.contains(maybeTable2)) { setMappedBy(ctField, mappedByFieldName, "ManyToMany"); finalTableName = maybeTable2; } setManyToManyHint(other); } findAndRemoveMethod(ctClass, ctField, mappedByClassName); findAndRemoveMethod(ctClass, ctField.getName()); String propertyName = mappedByFieldName.substring(0, 1).toUpperCase() + mappedByFieldName.substring(1); String getter = "get" + propertyName; CtMethod wow = CtMethod.make( format( "public net.csdn.jpa.association.Association {}() {" + "net.csdn.jpa.association.Association obj = new net.csdn.jpa.association.Association(this,\"{}\",\"{}\",\"{}\",\"{}\",\"{}\");return obj;" + " }", ctField.getName(), ctField.getName(), mappedByFieldName, "javax.persistence.ManyToMany", finalTableName, isMaster), ctClass); ctClass.addMethod(wow); CtMethod wow2 = CtMethod.make( format( "public {} {}({} obj) {" + " {}.add(obj);" + " obj.{}().add(this);" + " return this;" + " }", ctClass.getName(), ctField.getName(), clzzName, ctField.getName(), getter), ctClass); ctClass.addMethod(wow2); } } ctClass.defrost(); }