@SuppressWarnings("unchecked")
    @Override
    protected void bodyEnd(EntityType model, CodeWriter writer) throws IOException {
        Collection<PrimaryKeyData> primaryKeys = (Collection<PrimaryKeyData>) model.getData().get(PrimaryKeyData.class);

        if (primaryKeys == null || primaryKeys.isEmpty()) {
            return;
        }

        Map<String, Property> columnToProperty = new HashMap<String, Property>();
        for (Property property : model.getProperties()) {
            columnToProperty.put(property.getAnnotation(Column.class).value(), property);
        }

        StringBuilder anyColumnIsNull = new StringBuilder();
        StringBuilder columnEquals = new StringBuilder();
        List<String> properties = new ArrayList<String>();
        for (PrimaryKeyData pk : primaryKeys) {
            for (String column : pk.getColumns()) {
                Property property = columnToProperty.get(column);
                String propName = property.getEscapedName();
                if (anyColumnIsNull.length() > 0) {
                    anyColumnIsNull.append(" || ");
                    columnEquals.append(" && ");
                }
                anyColumnIsNull.append(propName).append(" == null");
                columnEquals.append(propName).append(".equals(obj.").append(propName).append(")");
                properties.add(propName);
            }
        }

        // equals
        writer.annotation(Override.class);
        writer.beginPublicMethod(Types.BOOLEAN_P, "equals", o);
        writer.line("if (", anyColumnIsNull + ") {");
        writer.line("    return super.equals(o);");
        writer.line("}");
        writer.line("if (!(o instanceof ", model.getSimpleName(), ")) {");
        writer.line("    return false;");
        writer.line("}");
        writer.line(model.getSimpleName(), " obj = (", model.getSimpleName(), ") o;");
        writer.line("return ", columnEquals + ";");
        writer.end();

        // hashCode
        writer.annotation(Override.class);
        writer.beginPublicMethod(Types.INT, "hashCode");
        writer.line("if (", anyColumnIsNull + ") {");
        writer.line("    return super.hashCode();");
        writer.line("}");
        writer.line("final int prime = 31;");
        writer.line("int result = 1;");
        for (String property : properties) {
            writer.line("result = prime * result + ", property, ".hashCode();");
        }
        writer.line("return result;");
        writer.end();


    }
Create a new ExtendedBeanSerializer with the given javadoc suffix and generatedAnnotationClass

@param javadocSuffix suffix to be used after the simple name in class level javadoc
@param generatedAnnotationClass the fully qualified class name of the <em>Single-Element Annotation</em> (with {@code String} element) to be used on the generated classes.
@see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.7.3">Single-Element Annotation</a>
querydsl-sql-codegen/src/main/java/com/querydsl/sql/codegen/ExtendedBeanSerializer.java