Search in sources :

Example 1 with JoinTable

use of javax.persistence.JoinTable in project eweb4j-framework by laiweiwei.

the class OneToManyDAO method delete.

/**
	 * 
	 * 一对多(主从)级联删除 
	 * 1.前提条件必须主对象要存在于数据库中
	 * 2.检查当前主对象中的关联对象,如果关联对象为空,则删除所有与主对象有关的关联关系。
	 * 3.如果当前主对象中含有关联对象,则删除这些关联对象与主对象的关系
	 * 4.不会删除主对象
	 */
public void delete() throws DAOException {
    if (this.fields == null || this.fields.size() == 0)
        return;
    final Class<?> ownClass = ru.getObject().getClass();
    Transaction.execute(new Trans() {

        @Override
        public void run(Object... args) throws Exception {
            for (Field f : fields) {
                Method tarGetter = ru.getGetter(f.getName());
                if (tarGetter == null)
                    continue;
                OneToMany ann = tarGetter.getAnnotation(OneToMany.class);
                if (ann == null) {
                    ann = f.getAnnotation(OneToMany.class);
                    if (ann == null)
                        continue;
                }
                String mappedBy = ann.mappedBy();
                Class<?> tarClass = ann.targetEntity();
                if (void.class.isAssignableFrom(tarClass))
                    tarClass = ClassUtil.getGenericType(f);
                List<?> tarList = null;
                try {
                    tarList = (List<?>) tarGetter.invoke(t);
                } catch (Exception e) {
                    throw new DAOException(tarGetter + " invoke exception ", e);
                }
                if (tarList == null || tarList.size() == 0) {
                    // 当关联对象为空的时候,删除所有关联对象
                    ReflectUtil tarRu = new ReflectUtil(tarClass);
                    if (mappedBy == null || mappedBy.trim().length() == 0) {
                        for (Field tarObjField : tarRu.getFields()) {
                            if (!tarObjField.getType().getName().equals(ownClass.getName()))
                                continue;
                            Method tarObjFieldGetter = tarRu.getGetter(tarObjField.getName());
                            if (tarObjFieldGetter == null)
                                continue;
                            ManyToOne manyToOne = tarObjField.getAnnotation(ManyToOne.class);
                            if (manyToOne == null)
                                manyToOne = tarObjFieldGetter.getAnnotation(ManyToOne.class);
                            if (manyToOne == null)
                                continue;
                            mappedBy = tarObjField.getName();
                            String fromRefCol = null;
                            JoinColumn joinCol = tarObjField.getAnnotation(JoinColumn.class);
                            if (joinCol == null)
                                joinCol = tarObjFieldGetter.getAnnotation(JoinColumn.class);
                            if (joinCol != null)
                                fromRefCol = joinCol.referencedColumnName();
                            if (fromRefCol == null || fromRefCol.trim().length() == 0)
                                fromRefCol = ORMConfigBeanUtil.getIdColumn(t);
                            String fromRefField = ORMConfigBeanUtil.getField(ownClass, fromRefCol);
                            Method fromRefFieldGetter = ru.getGetter(fromRefField);
                            if (fromRefFieldGetter == null)
                                throw new Exception("can not find the 'from ref field field -> " + fromRefField + "' of " + ownClass + " 's getter method");
                            String fromRefVal = null;
                            Object _obj = fromRefFieldGetter.invoke(t);
                            if (_obj != null)
                                fromRefVal = String.valueOf(_obj);
                            DAOFactory.getDeleteDAO(dsName).deleteByFieldIsValue(tarClass, new String[] { tarObjField.getName() }, new String[] { fromRefVal });
                            break;
                        }
                    }
                } else {
                    // 当关联对象不为空的时候,删除这些关联对象
                    for (int i = 0; i < tarList.size(); i++) {
                        Object tarObj = tarList.get(i);
                        if (tarObj == null)
                            continue;
                        //如果这些对象没有ID值,跳过
                        Object tarObjIdVal = ORMConfigBeanUtil.getIdVal(tarObj);
                        if (tarObjIdVal == null)
                            continue;
                        ReflectUtil tarRu = new ReflectUtil(tarObj);
                        if (mappedBy != null && mappedBy.trim().length() > 0) {
                            Method ownFieldSetter = tarRu.getSetter(mappedBy);
                            if (ownFieldSetter == null)
                                continue;
                            // finished
                            DAOFactory.getDeleteDAO(dsName).deleteById(tarObj);
                        } else {
                            JoinTable joinTable = null;
                            if (f.isAnnotationPresent(JoinTable.class)) {
                                joinTable = f.getAnnotation(JoinTable.class);
                            } else if (tarGetter.isAnnotationPresent(JoinTable.class)) {
                                joinTable = tarGetter.getAnnotation(JoinTable.class);
                            } else {
                                // find ownclass in tarObj fields
                                for (Field tarObjField : tarRu.getFields()) {
                                    if (!tarObjField.getType().getName().equals(ownClass.getName()))
                                        continue;
                                    Method tarObjFieldGetter = tarRu.getGetter(tarObjField.getName());
                                    if (tarObjFieldGetter == null)
                                        continue;
                                    ManyToOne manyToOne = tarObjField.getAnnotation(ManyToOne.class);
                                    if (manyToOne == null)
                                        manyToOne = tarObjFieldGetter.getAnnotation(ManyToOne.class);
                                    if (manyToOne == null)
                                        continue;
                                    String fromRefCol = null;
                                    JoinColumn joinCol = tarObjField.getAnnotation(JoinColumn.class);
                                    if (joinCol == null)
                                        joinCol = tarObjFieldGetter.getAnnotation(JoinColumn.class);
                                    if (joinCol != null)
                                        fromRefCol = joinCol.referencedColumnName();
                                    if (fromRefCol == null || fromRefCol.trim().length() == 0)
                                        fromRefCol = ORMConfigBeanUtil.getIdColumn(t);
                                    String fromRefField = ORMConfigBeanUtil.getField(ownClass, fromRefCol);
                                    Method fromRefFieldGetter = ru.getGetter(fromRefField);
                                    if (fromRefFieldGetter == null)
                                        throw new Exception("can not find the 'from ref field field -> " + fromRefField + "' of " + ownClass + " 's getter method");
                                    String fromRefVal = null;
                                    Object _obj = fromRefFieldGetter.invoke(t);
                                    if (_obj != null)
                                        fromRefVal = String.valueOf(_obj);
                                    DAOFactory.getDeleteDAO(dsName).deleteByFieldIsValue(tarClass, new String[] { tarObjField.getName() }, new String[] { fromRefVal });
                                    break;
                                }
                            }
                            if (joinTable != null) {
                                JoinColumn[] froms = joinTable.joinColumns();
                                if (froms == null || froms.length == 0)
                                    continue;
                                String from = froms[0].name();
                                JoinColumn[] tos = joinTable.inverseJoinColumns();
                                if (tos == null || tos.length == 0)
                                    continue;
                                String to = tos[0].name();
                                String relTable = joinTable.name();
                                String fromRefCol = froms[0].referencedColumnName();
                                if (fromRefCol == null || fromRefCol.trim().length() == 0)
                                    fromRefCol = ORMConfigBeanUtil.getIdColumn(t);
                                String fromRefField = ORMConfigBeanUtil.getField(t.getClass(), fromRefCol);
                                Method fromRefFieldGetter = ru.getGetter(fromRefField);
                                if (fromRefFieldGetter == null)
                                    throw new Exception("can not find the 'from ref field -> " + fromRefField + "' of " + t.getClass() + " 's getter method");
                                Object _obj = fromRefFieldGetter.invoke(t);
                                if (_obj == null)
                                    continue;
                                String fromRefVal = String.valueOf(_obj);
                                String toRefCol = tos[0].referencedColumnName();
                                if (toRefCol == null || toRefCol.trim().length() == 0)
                                    toRefCol = ORMConfigBeanUtil.getIdColumn(tarClass);
                                String toRefField = ORMConfigBeanUtil.getField(tarClass, toRefCol);
                                Method toRefFieldGetter = tarRu.getGetter(toRefField);
                                if (toRefFieldGetter == null)
                                    throw new Exception("can not find the 'to ref field -> " + toRefField + "' of " + tarClass + " 's getter method");
                                Object _obj2 = toRefFieldGetter.invoke(tarObj);
                                if (_obj2 == null)
                                    continue;
                                String toRefVal = String.valueOf(_obj2);
                                // delete from relTable where from = ? and to = ? ;
                                String format = "delete from %s where %s = ? and %s = ? ;";
                                String sql = String.format(format, relTable, from, to);
                                // finished
                                DAOFactory.getUpdateDAO(dsName).updateBySQLWithArgs(sql, fromRefVal, toRefVal);
                            }
                        }
                    }
                }
            }
        }
    });
}
Also used : Method(java.lang.reflect.Method) OneToMany(javax.persistence.OneToMany) DAOException(org.eweb4j.orm.dao.DAOException) ManyToOne(javax.persistence.ManyToOne) DAOException(org.eweb4j.orm.dao.DAOException) Field(java.lang.reflect.Field) ReflectUtil(org.eweb4j.util.ReflectUtil) JoinColumn(javax.persistence.JoinColumn) List(java.util.List) Trans(org.eweb4j.orm.jdbc.transaction.Trans) JoinTable(javax.persistence.JoinTable)

Example 2 with JoinTable

use of javax.persistence.JoinTable in project eweb4j-framework by laiweiwei.

the class OneToManyDAO method select.

/**
	 * 一对多(主从)级联查询
	 */
public void select() throws DAOException {
    if (this.fields == null || this.fields.size() == 0)
        return;
    Class<?> ownClass = ru.getObject().getClass();
    String fromRefVal = null;
    for (Field f : fields) {
        Method tarGetter = ru.getGetter(f.getName());
        if (tarGetter == null)
            continue;
        OneToMany ann = tarGetter.getAnnotation(OneToMany.class);
        if (ann == null) {
            ann = f.getAnnotation(OneToMany.class);
            if (ann == null)
                continue;
        }
        OrderBy orderAnn = tarGetter.getAnnotation(OrderBy.class);
        if (orderAnn == null)
            orderAnn = f.getAnnotation(OrderBy.class);
        Class<?> tarClass = ann.targetEntity();
        if (void.class.isAssignableFrom(tarClass))
            tarClass = ClassUtil.getGenericType(f);
        String orderBy = "";
        if (orderAnn != null && orderAnn.value().trim().length() > 0)
            orderBy = " ORDER BY " + orderAnn.value().replace("t.", tarClass.getSimpleName().toLowerCase() + ".");
        String mappedBy = ann.mappedBy();
        try {
            ReflectUtil tarRu = new ReflectUtil(tarClass);
            List<?> tarList = null;
            JoinTable joinTable = null;
            if (f.isAnnotationPresent(JoinTable.class)) {
                joinTable = f.getAnnotation(JoinTable.class);
            } else if (tarGetter.isAnnotationPresent(JoinTable.class)) {
                joinTable = tarGetter.getAnnotation(JoinTable.class);
            }
            // 如果用户填写了 JoinTable注解,说明是第三方表建立的关联关系,需要查询第三方表和字段才能获取到targetList
            if (joinTable != null) {
                JoinColumn[] froms = joinTable.joinColumns();
                if (froms == null || froms.length == 0)
                    continue;
                String tarTable = joinTable.name();
                String from = froms[0].name();
                String fromRefCol = froms[0].referencedColumnName();
                if (fromRefCol == null || fromRefCol.trim().length() == 0)
                    fromRefCol = ORMConfigBeanUtil.getIdColumn(t);
                String fromRefField = ORMConfigBeanUtil.getField(t.getClass(), fromRefCol);
                Method fromRefFieldGetter = ru.getGetter(fromRefField);
                if (fromRefFieldGetter == null)
                    throw new Exception("can not find the 'from ref field -> " + fromRefField + "' of " + t.getClass() + " 's getter method");
                Object _obj = fromRefFieldGetter.invoke(t);
                if (_obj == null)
                    continue;
                fromRefVal = String.valueOf(_obj);
                String format = "select %s from %s where %s = ?  ;";
                String sql = String.format(format, ORMConfigBeanUtil.getSelectAllColumn(tarClass), tarTable, from) + orderBy;
                // finished
                tarList = DAOFactory.getSelectDAO(dsName).selectBySQL(tarClass, sql, fromRefVal);
            } else {
                // 否则的话按照ManyToOne去查询
                // 如果给定了 mappedBy,直接用这个mappedBy来获取filed,否则遍历。
                Field mappedField = null;
                if (mappedBy != null && mappedBy.trim().length() > 0) {
                    mappedField = tarRu.getField(mappedBy);
                } else {
                    for (Field field : tarRu.getFields()) {
                        if (!field.getType().getName().equals(ownClass.getName()))
                            continue;
                        mappedField = field;
                        mappedBy = mappedField.getName();
                        break;
                    }
                }
                if (mappedField == null)
                    throw new Exception("mapped field of " + tarClass + " not found");
                Method tarObjFieldGetter = tarRu.getGetter(mappedBy);
                if (tarObjFieldGetter == null)
                    continue;
                ManyToOne manyToOne = mappedField.getAnnotation(ManyToOne.class);
                if (manyToOne == null)
                    manyToOne = tarObjFieldGetter.getAnnotation(ManyToOne.class);
                if (manyToOne == null)
                    continue;
                String fromRefCol = null;
                JoinColumn joinCol = mappedField.getAnnotation(JoinColumn.class);
                if (joinCol == null)
                    joinCol = tarObjFieldGetter.getAnnotation(JoinColumn.class);
                if (joinCol != null)
                    fromRefCol = joinCol.referencedColumnName();
                if (fromRefCol == null || fromRefCol.trim().length() == 0)
                    fromRefCol = ORMConfigBeanUtil.getIdColumn(t);
                String fromRefField = ORMConfigBeanUtil.getField(ownClass, fromRefCol);
                Method fromRefFieldGetter = ru.getGetter(fromRefField);
                if (fromRefFieldGetter == null)
                    throw new Exception("can not find the 'from ref field field -> " + fromRefField + "' of " + ownClass + " 's getter method");
                Object _obj = fromRefFieldGetter.invoke(t);
                if (_obj != null)
                    fromRefVal = String.valueOf(_obj);
                String format = "select %s from %s where %s = ?  ;";
                String sql = String.format(format, ORMConfigBeanUtil.getSelectAllColumn(tarClass), ORMConfigBeanUtil.getTable(tarClass, true), ORMConfigBeanUtil.getColumn(tarClass, mappedBy)) + orderBy;
                // finished
                tarList = DAOFactory.getSelectDAO(dsName).selectBySQL(tarClass, sql, fromRefVal);
            }
            if (tarList == null)
                continue;
            Method tarSetter = ru.getSetter(f.getName());
            if (tarSetter == null)
                continue;
            tarSetter.invoke(t, tarList);
        } catch (Exception e) {
            throw new DAOException("", e);
        }
    }
}
Also used : OrderBy(javax.persistence.OrderBy) Method(java.lang.reflect.Method) OneToMany(javax.persistence.OneToMany) DAOException(org.eweb4j.orm.dao.DAOException) ManyToOne(javax.persistence.ManyToOne) DAOException(org.eweb4j.orm.dao.DAOException) Field(java.lang.reflect.Field) ReflectUtil(org.eweb4j.util.ReflectUtil) JoinColumn(javax.persistence.JoinColumn) JoinTable(javax.persistence.JoinTable)

Example 3 with JoinTable

use of javax.persistence.JoinTable in project eweb4j-framework by laiweiwei.

the class Model2Table method generateOne.

public static String generateOne(final Class<?> entityClass, final boolean isDrop, boolean isCreateFile) {
    StringBuilder sql = new StringBuilder();
    StringBuilder manyMany = new StringBuilder();
    final ORMConfigBean ocb = ORMConfigBeanCache.get(entityClass.getName());
    final String table = ocb.getTable();
    List<Property> properties = ocb.getProperty();
    StringBuilder sb = new StringBuilder();
    StringBuilder fkSb = new StringBuilder();
    final String fk = ", \n\tKEY %s (%s), \n\tCONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)";
    StringBuilder pkSb = new StringBuilder();
    final String pk = ", \n\tPRIMARY KEY (%s)";
    StringBuilder uniqueSb = new StringBuilder();
    String unique = ", \n\tUNIQUE KEY %s (%s)";
    final String idCol = ORMConfigBeanUtil.getIdColumn(properties);
    for (Property p : properties) {
        if (sb.length() > 0)
            sb.append(", \n");
        String col = p.getColumn();
        String type = p.getType();
        String size = null;
        if (p.getSize().trim().length() > 0 && CommonUtil.isNumeric(p.getSize().trim()))
            size = String.format(" (%s) ", p.getSize());
        if ("1".equals(p.getUnique()) || "true".equalsIgnoreCase(p.getUnique()))
            uniqueSb.append(String.format(unique, col, col));
        String notNull = "";
        if ("1".equals(p.getNotNull()) || "true".equalsIgnoreCase(p.getNotNull()))
            notNull = " NOT NULL ";
        if ("1".equals(p.getPk()) || "true".equalsIgnoreCase(p.getPk())) {
            if (pkSb.length() > 0)
                pkSb.append(",");
            pkSb.append(col);
        }
        String auto = "";
        if ("1".equals(p.getAutoIncrement()) || "true".equalsIgnoreCase(p.getAutoIncrement()))
            auto = " AUTO_INCREMENT ";
        if (PropType.ONE_ONE.equals(p.getType()) || PropType.MANY_ONE.equals(p.getType())) {
            final String relTable = ORMConfigBeanUtil.getTable(p.getRelClass(), false);
            if (p.getRelProperty() == null || p.getRelProperty().trim().length() == 0)
                p.setRelProperty(ORMConfigBeanUtil.getIdField(p.getRelClass()));
            final String relColumn = ORMConfigBeanUtil.getColumn(p.getRelClass(), p.getRelProperty());
            fkSb.append(String.format(fk, col, col, table + "_" + col, col, relTable, relColumn));
        }
        sb.append("\t").append(col).append(" ").append(getType(type)).append(size == null ? "" : size).append(notNull).append(auto);
    }
    sb.append(uniqueSb.toString());
    if (pkSb.length() > 0)
        sb.append(String.format(pk, pkSb.toString()));
    sb.append(fkSb.toString());
    String _sql = String.format(create_table_script, table, sb.toString());
    if (isDrop) {
        _sql = String.format(drop_table_script, table) + _sql;
        ;
    }
    sql.append(_sql);
    try {
        ReflectUtil ru = new ReflectUtil(entityClass);
        for (Field f : ru.getFields()) {
            if (!ClassUtil.isListClass(f))
                continue;
            String name = f.getName();
            Method getter = ru.getGetter(name);
            if (getter == null)
                continue;
            ManyToMany mmAnn = getter.getAnnotation(ManyToMany.class);
            if (mmAnn == null)
                mmAnn = f.getAnnotation(ManyToMany.class);
            if (mmAnn != null) {
                JoinTable join = getter.getAnnotation(JoinTable.class);
                if (join == null) {
                    join = f.getAnnotation(JoinTable.class);
                    if (join == null)
                        continue;
                }
                JoinColumn[] froms = join.joinColumns();
                if (froms == null || froms.length == 0)
                    continue;
                JoinColumn[] tos = join.inverseJoinColumns();
                if (tos == null || tos.length == 0)
                    continue;
                final String relTable = join.name();
                final String relFrom = froms[0].name();
                final String relTo = tos[0].name();
                final Class<?> targetClass = ClassUtil.getGenericType(f);
                StringBuilder manyManyField = new StringBuilder();
                //handle the many to many 
                manyManyField.append("\tid ").append(getType("long")).append(" (20) NOT NULL AUTO_INCREMENT,");
                manyManyField.append("\n\t").append(relFrom).append(" ").append(getType("long")).append(" (20) ,");
                manyManyField.append("\n\t").append(relTo).append(" ").append(getType("long")).append(" (20) ,");
                manyManyField.append("\n\t").append("PRIMARY KEY (id)");
                String tarTable = ORMConfigBeanUtil.getTable(targetClass, false);
                String tarIdCol = ORMConfigBeanUtil.getIdColumn(targetClass);
                String fk1 = String.format(fk, relFrom, relFrom, relTable + "_" + relFrom, relFrom, table, idCol);
                manyManyField.append(fk1);
                String fk2 = String.format(fk, relTo, relTo, relTable + "_" + relTo, relTo, tarTable, tarIdCol);
                manyManyField.append(fk2);
                manyMany.append(String.format(create_table_script, relTable, relTable, manyManyField.toString()));
            }
        }
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    sql.append(manyMany.toString());
    String script = String.format("SET FOREIGN_KEY_CHECKS=0;\n%s", sql.toString());
    if (!isCreateFile)
        return script;
    try {
        ConfigBean cb = (ConfigBean) SingleBeanCache.get(ConfigBean.class.getName());
        File file = new File(ConfigConstant.CONFIG_BASE_PATH() + cb.getOrm().getDdl().getDs() + "-create.sql");
        FileWriter writer = new FileWriter(file);
        writer.write(script);
        writer.flush();
        writer.close();
        LogFactory.getORMLogger(Model2Table.class).debug("create models sql script file success -> " + file.getAbsoluteFile());
        return script;
    } catch (IOException e2) {
        e2.printStackTrace();
        return null;
    }
}
Also used : ORMConfigBean(org.eweb4j.orm.config.bean.ORMConfigBean) FileWriter(java.io.FileWriter) ManyToMany(javax.persistence.ManyToMany) Method(java.lang.reflect.Method) ORMConfigBean(org.eweb4j.orm.config.bean.ORMConfigBean) ConfigBean(org.eweb4j.config.bean.ConfigBean) IOException(java.io.IOException) IOException(java.io.IOException) ReflectUtil(org.eweb4j.util.ReflectUtil) Field(java.lang.reflect.Field) JoinColumn(javax.persistence.JoinColumn) Property(org.eweb4j.orm.config.bean.Property) File(java.io.File) JoinTable(javax.persistence.JoinTable)

Example 4 with JoinTable

use of javax.persistence.JoinTable in project eweb4j-framework by laiweiwei.

the class Model2Table method generateAll.

public static String generateAll(final boolean isDrop, final boolean isCreateFile) {
    StringBuilder sql = new StringBuilder();
    StringBuilder manyMany = new StringBuilder();
    for (Iterator<Entry<Object, ORMConfigBean>> it = ORMConfigBeanCache.entrySet().iterator(); it.hasNext(); ) {
        final Entry<Object, ORMConfigBean> e = it.next();
        final ORMConfigBean ocb = e.getValue();
        final String table = ocb.getTable();
        List<Property> properties = ocb.getProperty();
        StringBuilder sb = new StringBuilder();
        StringBuilder fkSb = new StringBuilder();
        final String fk = ", \n\tKEY %s (%s), \n\tCONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)";
        StringBuilder pkSb = new StringBuilder();
        final String pk = ", \n\tPRIMARY KEY (%s)";
        StringBuilder uniqueSb = new StringBuilder();
        String unique = ", \n\tUNIQUE KEY %s (%s)";
        final String idCol = ORMConfigBeanUtil.getIdColumn(properties);
        for (Property p : properties) {
            if (sb.length() > 0)
                sb.append(", \n");
            String col = p.getColumn();
            String type = p.getType();
            String size = null;
            if (p.getSize().trim().length() > 0 && CommonUtil.isNumeric(p.getSize().trim()))
                size = String.format(" (%s) ", p.getSize());
            if ("1".equals(p.getUnique()) || "true".equalsIgnoreCase(p.getUnique()))
                uniqueSb.append(String.format(unique, col, col));
            String notNull = "";
            if ("1".equals(p.getNotNull()) || "true".equalsIgnoreCase(p.getNotNull()))
                notNull = " NOT NULL ";
            if ("1".equals(p.getPk()) || "true".equalsIgnoreCase(p.getPk())) {
                if (pkSb.length() > 0)
                    pkSb.append(",");
                pkSb.append(col);
            }
            String auto = "";
            if ("1".equals(p.getAutoIncrement()) || "true".equalsIgnoreCase(p.getAutoIncrement()))
                auto = " AUTO_INCREMENT ";
            if (PropType.ONE_ONE.equals(p.getType()) || PropType.MANY_ONE.equals(p.getType())) {
                final String relTable = ORMConfigBeanUtil.getTable(p.getRelClass(), false);
                if (p.getRelProperty() == null || p.getRelProperty().trim().length() == 0)
                    p.setRelProperty(ORMConfigBeanUtil.getIdField(p.getRelClass()));
                final String relColumn = ORMConfigBeanUtil.getColumn(p.getRelClass(), p.getRelProperty());
                fkSb.append(String.format(fk, col, col, table + "_" + col, col, relTable, relColumn));
            }
            sb.append("\t").append(col).append(" ").append(getType(type)).append(size == null ? "" : size).append(notNull).append(auto);
        }
        sb.append(uniqueSb.toString());
        if (pkSb.length() > 0)
            sb.append(String.format(pk, pkSb.toString()));
        sb.append(fkSb.toString());
        String _sql = String.format(create_table_script, table, sb.toString());
        if (isDrop) {
            _sql = String.format(drop_table_script, table) + _sql;
            ;
        }
        sql.append(_sql);
        try {
            Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass((String) e.getKey());
            ReflectUtil ru = new ReflectUtil(clazz);
            for (Field f : ru.getFields()) {
                if (!ClassUtil.isListClass(f))
                    continue;
                String name = f.getName();
                Method getter = ru.getGetter(name);
                if (getter == null)
                    continue;
                ManyToMany mmAnn = getter.getAnnotation(ManyToMany.class);
                if (mmAnn == null)
                    mmAnn = f.getAnnotation(ManyToMany.class);
                if (mmAnn != null) {
                    JoinTable join = getter.getAnnotation(JoinTable.class);
                    if (join == null) {
                        join = f.getAnnotation(JoinTable.class);
                        if (join == null)
                            continue;
                    }
                    JoinColumn[] froms = join.joinColumns();
                    if (froms == null || froms.length == 0)
                        continue;
                    JoinColumn[] tos = join.inverseJoinColumns();
                    if (tos == null || tos.length == 0)
                        continue;
                    final String relTable = join.name();
                    final String relFrom = froms[0].name();
                    final String relTo = tos[0].name();
                    final Class<?> targetClass = ClassUtil.getGenericType(f);
                    StringBuilder manyManyField = new StringBuilder();
                    //handle the many to many 
                    manyManyField.append("\tid ").append(getType("long")).append(" (20) NOT NULL AUTO_INCREMENT,");
                    manyManyField.append("\n\t").append(relFrom).append(" ").append(getType("long")).append(" (20) ,");
                    manyManyField.append("\n\t").append(relTo).append(" ").append(getType("long")).append(" (20) ,");
                    manyManyField.append("\n\t").append("PRIMARY KEY (id)");
                    String tarTable = ORMConfigBeanUtil.getTable(targetClass, false);
                    String tarIdCol = ORMConfigBeanUtil.getIdColumn(targetClass);
                    String fk1 = String.format(fk, relFrom, relFrom, relTable + "_" + relFrom, relFrom, table, idCol);
                    manyManyField.append(fk1);
                    String fk2 = String.format(fk, relTo, relTo, relTable + "_" + relTo, relTo, tarTable, tarIdCol);
                    manyManyField.append(fk2);
                    manyMany.append(String.format(create_table_script, relTable, relTable, manyManyField.toString()));
                }
            }
        } catch (Exception e1) {
            continue;
        }
    }
    sql.append(manyMany.toString());
    String script = String.format("SET FOREIGN_KEY_CHECKS=0;\n%s", sql.toString());
    if (!isCreateFile)
        return script;
    try {
        ConfigBean cb = (ConfigBean) SingleBeanCache.get(ConfigBean.class.getName());
        File file = new File(ConfigConstant.CONFIG_BASE_PATH() + cb.getOrm().getDdl().getDs() + "-create.sql");
        FileWriter writer = new FileWriter(file);
        writer.write(script);
        writer.flush();
        writer.close();
        LogFactory.getORMLogger(Model2Table.class).debug("create models sql script file success -> " + file.getAbsoluteFile());
        return script;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
Also used : ORMConfigBean(org.eweb4j.orm.config.bean.ORMConfigBean) FileWriter(java.io.FileWriter) ManyToMany(javax.persistence.ManyToMany) Method(java.lang.reflect.Method) ORMConfigBean(org.eweb4j.orm.config.bean.ORMConfigBean) ConfigBean(org.eweb4j.config.bean.ConfigBean) IOException(java.io.IOException) IOException(java.io.IOException) ReflectUtil(org.eweb4j.util.ReflectUtil) Field(java.lang.reflect.Field) Entry(java.util.Map.Entry) JoinColumn(javax.persistence.JoinColumn) Property(org.eweb4j.orm.config.bean.Property) File(java.io.File) JoinTable(javax.persistence.JoinTable)

Example 5 with JoinTable

use of javax.persistence.JoinTable in project hibernate-orm by hibernate.

the class AnnotationBinder method processElementAnnotations.

/*
	 * Process annotation of a particular property
	 */
private static void processElementAnnotations(PropertyHolder propertyHolder, Nullability nullability, PropertyData inferredData, HashMap<String, IdentifierGeneratorDefinition> classGenerators, EntityBinder entityBinder, boolean isIdentifierMapper, boolean isComponentEmbedded, boolean inSecondPass, MetadataBuildingContext context, Map<XClass, InheritanceState> inheritanceStatePerClass) throws MappingException {
    if (!propertyHolder.isComponent()) {
        if (entityBinder.isPropertyDefinedInSuperHierarchy(inferredData.getPropertyName())) {
            LOG.debugf("Skipping attribute [%s : %s] as it was already processed as part of super hierarchy", inferredData.getClassOrElementName(), inferredData.getPropertyName());
            return;
        }
    }
    /**
		 * inSecondPass can only be used to apply right away the second pass of a composite-element
		 * Because it's a value type, there is no bidirectional association, hence second pass
		 * ordering does not matter
		 */
    final boolean traceEnabled = LOG.isTraceEnabled();
    if (traceEnabled) {
        LOG.tracev("Processing annotations of {0}.{1}", propertyHolder.getEntityName(), inferredData.getPropertyName());
    }
    final XProperty property = inferredData.getProperty();
    if (property.isAnnotationPresent(Parent.class)) {
        if (propertyHolder.isComponent()) {
            propertyHolder.setParentProperty(property.getName());
        } else {
            throw new AnnotationException("@Parent cannot be applied outside an embeddable object: " + BinderHelper.getPath(propertyHolder, inferredData));
        }
        return;
    }
    ColumnsBuilder columnsBuilder = new ColumnsBuilder(propertyHolder, nullability, property, inferredData, entityBinder, context).extractMetadata();
    Ejb3Column[] columns = columnsBuilder.getColumns();
    Ejb3JoinColumn[] joinColumns = columnsBuilder.getJoinColumns();
    final XClass returnedClass = inferredData.getClassOrElement();
    //prepare PropertyBinder
    PropertyBinder propertyBinder = new PropertyBinder();
    propertyBinder.setName(inferredData.getPropertyName());
    propertyBinder.setReturnedClassName(inferredData.getTypeName());
    propertyBinder.setAccessType(inferredData.getDefaultAccess());
    propertyBinder.setHolder(propertyHolder);
    propertyBinder.setProperty(property);
    propertyBinder.setReturnedClass(inferredData.getPropertyClass());
    propertyBinder.setBuildingContext(context);
    if (isIdentifierMapper) {
        propertyBinder.setInsertable(false);
        propertyBinder.setUpdatable(false);
    }
    propertyBinder.setDeclaringClass(inferredData.getDeclaringClass());
    propertyBinder.setEntityBinder(entityBinder);
    propertyBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
    boolean isId = !entityBinder.isIgnoreIdAnnotations() && (property.isAnnotationPresent(Id.class) || property.isAnnotationPresent(EmbeddedId.class));
    propertyBinder.setId(isId);
    final LazyGroup lazyGroupAnnotation = property.getAnnotation(LazyGroup.class);
    if (lazyGroupAnnotation != null) {
        propertyBinder.setLazyGroup(lazyGroupAnnotation.value());
    }
    if (property.isAnnotationPresent(Version.class)) {
        if (isIdentifierMapper) {
            throw new AnnotationException("@IdClass class should not have @Version property");
        }
        if (!(propertyHolder.getPersistentClass() instanceof RootClass)) {
            throw new AnnotationException("Unable to define/override @Version on a subclass: " + propertyHolder.getEntityName());
        }
        if (!propertyHolder.isEntity()) {
            throw new AnnotationException("Unable to define @Version on an embedded class: " + propertyHolder.getEntityName());
        }
        if (traceEnabled) {
            LOG.tracev("{0} is a version property", inferredData.getPropertyName());
        }
        RootClass rootClass = (RootClass) propertyHolder.getPersistentClass();
        propertyBinder.setColumns(columns);
        Property prop = propertyBinder.makePropertyValueAndBind();
        setVersionInformation(property, propertyBinder);
        rootClass.setVersion(prop);
        //If version is on a mapped superclass, update the mapping
        final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(inferredData.getDeclaringClass(), inheritanceStatePerClass, context);
        if (superclass != null) {
            superclass.setDeclaredVersion(prop);
        } else {
            //we know the property is on the actual entity
            rootClass.setDeclaredVersion(prop);
        }
        SimpleValue simpleValue = (SimpleValue) prop.getValue();
        simpleValue.setNullValue("undefined");
        rootClass.setOptimisticLockStyle(OptimisticLockStyle.VERSION);
        if (traceEnabled) {
            LOG.tracev("Version name: {0}, unsavedValue: {1}", rootClass.getVersion().getName(), ((SimpleValue) rootClass.getVersion().getValue()).getNullValue());
        }
    } else {
        final boolean forcePersist = property.isAnnotationPresent(MapsId.class) || property.isAnnotationPresent(Id.class);
        if (property.isAnnotationPresent(ManyToOne.class)) {
            ManyToOne ann = property.getAnnotation(ManyToOne.class);
            //check validity
            if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
                throw new AnnotationException("@Column(s) not allowed on a @ManyToOne property: " + BinderHelper.getPath(propertyHolder, inferredData));
            }
            Cascade hibernateCascade = property.getAnnotation(Cascade.class);
            NotFound notFound = property.getAnnotation(NotFound.class);
            boolean ignoreNotFound = notFound != null && notFound.action().equals(NotFoundAction.IGNORE);
            OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
            boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
            JoinTable assocTable = propertyHolder.getJoinTable(property);
            if (assocTable != null) {
                Join join = propertyHolder.addJoin(assocTable, false);
                for (Ejb3JoinColumn joinColumn : joinColumns) {
                    joinColumn.setExplicitTableName(join.getTable().getName());
                }
            }
            final boolean mandatory = !ann.optional() || forcePersist;
            bindManyToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, false, forcePersist), joinColumns, !mandatory, ignoreNotFound, onDeleteCascade, ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, false, isIdentifierMapper, inSecondPass, propertyBinder, context);
        } else if (property.isAnnotationPresent(OneToOne.class)) {
            OneToOne ann = property.getAnnotation(OneToOne.class);
            //check validity
            if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
                throw new AnnotationException("@Column(s) not allowed on a @OneToOne property: " + BinderHelper.getPath(propertyHolder, inferredData));
            }
            //FIXME support a proper PKJCs
            boolean trueOneToOne = property.isAnnotationPresent(PrimaryKeyJoinColumn.class) || property.isAnnotationPresent(PrimaryKeyJoinColumns.class);
            Cascade hibernateCascade = property.getAnnotation(Cascade.class);
            NotFound notFound = property.getAnnotation(NotFound.class);
            boolean ignoreNotFound = notFound != null && notFound.action().equals(NotFoundAction.IGNORE);
            OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
            boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
            JoinTable assocTable = propertyHolder.getJoinTable(property);
            if (assocTable != null) {
                Join join = propertyHolder.addJoin(assocTable, false);
                for (Ejb3JoinColumn joinColumn : joinColumns) {
                    joinColumn.setExplicitTableName(join.getTable().getName());
                }
            }
            //MapsId means the columns belong to the pk => not null
            //@OneToOne with @PKJC can still be optional
            final boolean mandatory = !ann.optional() || forcePersist;
            bindOneToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist), joinColumns, !mandatory, getFetchMode(ann.fetch()), ignoreNotFound, onDeleteCascade, ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, inSecondPass, propertyBinder, context);
        } else if (property.isAnnotationPresent(org.hibernate.annotations.Any.class)) {
            //check validity
            if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
                throw new AnnotationException("@Column(s) not allowed on a @Any property: " + BinderHelper.getPath(propertyHolder, inferredData));
            }
            Cascade hibernateCascade = property.getAnnotation(Cascade.class);
            OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
            boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
            JoinTable assocTable = propertyHolder.getJoinTable(property);
            if (assocTable != null) {
                Join join = propertyHolder.addJoin(assocTable, false);
                for (Ejb3JoinColumn joinColumn : joinColumns) {
                    joinColumn.setExplicitTableName(join.getTable().getName());
                }
            }
            bindAny(getCascadeStrategy(null, hibernateCascade, false, forcePersist), //@Any has not cascade attribute
            joinColumns, onDeleteCascade, nullability, propertyHolder, inferredData, entityBinder, isIdentifierMapper, context);
        } else if (property.isAnnotationPresent(OneToMany.class) || property.isAnnotationPresent(ManyToMany.class) || property.isAnnotationPresent(ElementCollection.class) || property.isAnnotationPresent(ManyToAny.class)) {
            OneToMany oneToManyAnn = property.getAnnotation(OneToMany.class);
            ManyToMany manyToManyAnn = property.getAnnotation(ManyToMany.class);
            ElementCollection elementCollectionAnn = property.getAnnotation(ElementCollection.class);
            if ((oneToManyAnn != null || manyToManyAnn != null || elementCollectionAnn != null) && isToManyAssociationWithinEmbeddableCollection(propertyHolder)) {
                throw new AnnotationException("@OneToMany, @ManyToMany or @ElementCollection cannot be used inside an @Embeddable that is also contained within an @ElementCollection: " + BinderHelper.getPath(propertyHolder, inferredData));
            }
            final IndexColumn indexColumn;
            if (property.isAnnotationPresent(OrderColumn.class)) {
                indexColumn = IndexColumn.buildColumnFromAnnotation(property.getAnnotation(OrderColumn.class), propertyHolder, inferredData, entityBinder.getSecondaryTables(), context);
                if (property.isAnnotationPresent(ListIndexBase.class)) {
                    indexColumn.setBase((property.getAnnotation(ListIndexBase.class)).value());
                }
            } else {
                //if @IndexColumn is not there, the generated IndexColumn is an implicit column and not used.
                //so we can leave the legacy processing as the default
                indexColumn = IndexColumn.buildColumnFromAnnotation(property.getAnnotation(org.hibernate.annotations.IndexColumn.class), propertyHolder, inferredData, context);
            }
            CollectionBinder collectionBinder = CollectionBinder.getCollectionBinder(propertyHolder.getEntityName(), property, !indexColumn.isImplicit(), property.isAnnotationPresent(MapKeyType.class), context);
            collectionBinder.setIndexColumn(indexColumn);
            collectionBinder.setMapKey(property.getAnnotation(MapKey.class));
            collectionBinder.setPropertyName(inferredData.getPropertyName());
            collectionBinder.setBatchSize(property.getAnnotation(BatchSize.class));
            collectionBinder.setJpaOrderBy(property.getAnnotation(javax.persistence.OrderBy.class));
            collectionBinder.setSqlOrderBy(property.getAnnotation(OrderBy.class));
            collectionBinder.setSort(property.getAnnotation(Sort.class));
            collectionBinder.setNaturalSort(property.getAnnotation(SortNatural.class));
            collectionBinder.setComparatorSort(property.getAnnotation(SortComparator.class));
            Cache cachAnn = property.getAnnotation(Cache.class);
            collectionBinder.setCache(cachAnn);
            collectionBinder.setPropertyHolder(propertyHolder);
            Cascade hibernateCascade = property.getAnnotation(Cascade.class);
            NotFound notFound = property.getAnnotation(NotFound.class);
            boolean ignoreNotFound = notFound != null && notFound.action().equals(NotFoundAction.IGNORE);
            collectionBinder.setIgnoreNotFound(ignoreNotFound);
            collectionBinder.setCollectionType(inferredData.getProperty().getElementClass());
            collectionBinder.setBuildingContext(context);
            collectionBinder.setAccessType(inferredData.getDefaultAccess());
            Ejb3Column[] elementColumns;
            //do not use "element" if you are a JPA 2 @ElementCollection only for legacy Hibernate mappings
            boolean isJPA2ForValueMapping = property.isAnnotationPresent(ElementCollection.class);
            PropertyData virtualProperty = isJPA2ForValueMapping ? inferredData : new WrappedInferredData(inferredData, "element");
            if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Formula.class)) {
                Column ann = property.getAnnotation(Column.class);
                Formula formulaAnn = property.getAnnotation(Formula.class);
                elementColumns = Ejb3Column.buildColumnFromAnnotation(new Column[] { ann }, formulaAnn, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
            } else if (property.isAnnotationPresent(Columns.class)) {
                Columns anns = property.getAnnotation(Columns.class);
                elementColumns = Ejb3Column.buildColumnFromAnnotation(anns.columns(), null, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
            } else {
                elementColumns = Ejb3Column.buildColumnFromAnnotation(null, null, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
            }
            {
                Column[] keyColumns = null;
                //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2
                Boolean isJPA2 = null;
                if (property.isAnnotationPresent(MapKeyColumn.class)) {
                    isJPA2 = Boolean.TRUE;
                    keyColumns = new Column[] { new MapKeyColumnDelegator(property.getAnnotation(MapKeyColumn.class)) };
                }
                //not explicitly legacy
                if (isJPA2 == null) {
                    isJPA2 = Boolean.TRUE;
                }
                //nullify empty array
                keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns : null;
                //"mapkey" is the legacy column name of the key column pre JPA 2
                PropertyData mapKeyVirtualProperty = new WrappedInferredData(inferredData, "mapkey");
                Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation(keyColumns, null, Nullability.FORCED_NOT_NULL, propertyHolder, isJPA2 ? inferredData : mapKeyVirtualProperty, isJPA2 ? "_KEY" : null, entityBinder.getSecondaryTables(), context);
                collectionBinder.setMapKeyColumns(mapColumns);
            }
            {
                JoinColumn[] joinKeyColumns = null;
                //JPA 2 has priority and has different default column values, differenciate legacy from JPA 2
                Boolean isJPA2 = null;
                if (property.isAnnotationPresent(MapKeyJoinColumns.class)) {
                    isJPA2 = Boolean.TRUE;
                    final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation(MapKeyJoinColumns.class).value();
                    joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
                    int index = 0;
                    for (MapKeyJoinColumn joinColumn : mapKeyJoinColumns) {
                        joinKeyColumns[index] = new MapKeyJoinColumnDelegator(joinColumn);
                        index++;
                    }
                    if (property.isAnnotationPresent(MapKeyJoinColumn.class)) {
                        throw new AnnotationException("@MapKeyJoinColumn and @MapKeyJoinColumns used on the same property: " + BinderHelper.getPath(propertyHolder, inferredData));
                    }
                } else if (property.isAnnotationPresent(MapKeyJoinColumn.class)) {
                    isJPA2 = Boolean.TRUE;
                    joinKeyColumns = new JoinColumn[] { new MapKeyJoinColumnDelegator(property.getAnnotation(MapKeyJoinColumn.class)) };
                }
                //not explicitly legacy
                if (isJPA2 == null) {
                    isJPA2 = Boolean.TRUE;
                }
                PropertyData mapKeyVirtualProperty = new WrappedInferredData(inferredData, "mapkey");
                Ejb3JoinColumn[] mapJoinColumns = Ejb3JoinColumn.buildJoinColumnsWithDefaultColumnSuffix(joinKeyColumns, null, entityBinder.getSecondaryTables(), propertyHolder, isJPA2 ? inferredData.getPropertyName() : mapKeyVirtualProperty.getPropertyName(), isJPA2 ? "_KEY" : null, context);
                collectionBinder.setMapKeyManyToManyColumns(mapJoinColumns);
            }
            //potential element
            collectionBinder.setEmbedded(property.isAnnotationPresent(Embedded.class));
            collectionBinder.setElementColumns(elementColumns);
            collectionBinder.setProperty(property);
            //TODO enhance exception with @ManyToAny and @CollectionOfElements
            if (oneToManyAnn != null && manyToManyAnn != null) {
                throw new AnnotationException("@OneToMany and @ManyToMany on the same property is not allowed: " + propertyHolder.getEntityName() + "." + inferredData.getPropertyName());
            }
            String mappedBy = null;
            if (oneToManyAnn != null) {
                for (Ejb3JoinColumn column : joinColumns) {
                    if (column.isSecondary()) {
                        throw new NotYetImplementedException("Collections having FK in secondary table");
                    }
                }
                collectionBinder.setFkJoinColumns(joinColumns);
                mappedBy = oneToManyAnn.mappedBy();
                collectionBinder.setTargetEntity(context.getBuildingOptions().getReflectionManager().toXClass(oneToManyAnn.targetEntity()));
                collectionBinder.setCascadeStrategy(getCascadeStrategy(oneToManyAnn.cascade(), hibernateCascade, oneToManyAnn.orphanRemoval(), false));
                collectionBinder.setOneToMany(true);
            } else if (elementCollectionAnn != null) {
                for (Ejb3JoinColumn column : joinColumns) {
                    if (column.isSecondary()) {
                        throw new NotYetImplementedException("Collections having FK in secondary table");
                    }
                }
                collectionBinder.setFkJoinColumns(joinColumns);
                mappedBy = "";
                final Class<?> targetElement = elementCollectionAnn.targetClass();
                collectionBinder.setTargetEntity(context.getBuildingOptions().getReflectionManager().toXClass(targetElement));
                //collectionBinder.setCascadeStrategy( getCascadeStrategy( embeddedCollectionAnn.cascade(), hibernateCascade ) );
                collectionBinder.setOneToMany(true);
            } else if (manyToManyAnn != null) {
                mappedBy = manyToManyAnn.mappedBy();
                collectionBinder.setTargetEntity(context.getBuildingOptions().getReflectionManager().toXClass(manyToManyAnn.targetEntity()));
                collectionBinder.setCascadeStrategy(getCascadeStrategy(manyToManyAnn.cascade(), hibernateCascade, false, false));
                collectionBinder.setOneToMany(false);
            } else if (property.isAnnotationPresent(ManyToAny.class)) {
                mappedBy = "";
                collectionBinder.setTargetEntity(context.getBuildingOptions().getReflectionManager().toXClass(void.class));
                collectionBinder.setCascadeStrategy(getCascadeStrategy(null, hibernateCascade, false, false));
                collectionBinder.setOneToMany(false);
            }
            collectionBinder.setMappedBy(mappedBy);
            bindJoinedTableAssociation(property, context, entityBinder, collectionBinder, propertyHolder, inferredData, mappedBy);
            OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
            boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
            collectionBinder.setCascadeDeleteEnabled(onDeleteCascade);
            if (isIdentifierMapper) {
                collectionBinder.setInsertable(false);
                collectionBinder.setUpdatable(false);
            }
            if (property.isAnnotationPresent(CollectionId.class)) {
                //do not compute the generators unless necessary
                HashMap<String, IdentifierGeneratorDefinition> localGenerators = (HashMap<String, IdentifierGeneratorDefinition>) classGenerators.clone();
                localGenerators.putAll(buildLocalGenerators(property, context));
                collectionBinder.setLocalGenerators(localGenerators);
            }
            collectionBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
            collectionBinder.setDeclaringClass(inferredData.getDeclaringClass());
            collectionBinder.bind();
        } else //Either a regular property or a basic @Id or @EmbeddedId while not ignoring id annotations
        if (!isId || !entityBinder.isIgnoreIdAnnotations()) {
            //define whether the type is a component or not
            boolean isComponent = false;
            //Overrides from @MapsId if needed
            boolean isOverridden = false;
            if (isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass()) {
                //the associated entity could be using an @IdClass making the overridden property a component
                final PropertyData overridingProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(isId, propertyHolder, property.getName(), context);
                if (overridingProperty != null) {
                    isOverridden = true;
                    final InheritanceState state = inheritanceStatePerClass.get(overridingProperty.getClassOrElement());
                    if (state != null) {
                        isComponent = isComponent || state.hasIdClassOrEmbeddedId();
                    }
                    //Get the new column
                    columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty(isId);
                }
            }
            isComponent = isComponent || property.isAnnotationPresent(Embedded.class) || property.isAnnotationPresent(EmbeddedId.class) || returnedClass.isAnnotationPresent(Embeddable.class);
            if (isComponent) {
                String referencedEntityName = null;
                if (isOverridden) {
                    final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(isId, propertyHolder, property.getName(), context);
                    referencedEntityName = mapsIdProperty.getClassOrElementName();
                }
                AccessType propertyAccessor = entityBinder.getPropertyAccessor(property);
                propertyBinder = bindComponent(inferredData, propertyHolder, propertyAccessor, entityBinder, isIdentifierMapper, context, isComponentEmbedded, isId, inheritanceStatePerClass, referencedEntityName, isOverridden ? (Ejb3JoinColumn[]) columns : null);
            } else {
                //provide the basic property mapping
                boolean optional = true;
                boolean lazy = false;
                if (property.isAnnotationPresent(Basic.class)) {
                    Basic ann = property.getAnnotation(Basic.class);
                    optional = ann.optional();
                    lazy = ann.fetch() == FetchType.LAZY;
                }
                //implicit type will check basic types and Serializable classes
                if (isId || (!optional && nullability != Nullability.FORCED_NULL)) {
                    //force columns to not null
                    for (Ejb3Column col : columns) {
                        if (isId && col.isFormula()) {
                            throw new CannotForceNonNullableException(String.format(Locale.ROOT, "Identifier property [%s] cannot contain formula mapping [%s]", HCANNHelper.annotatedElementSignature(property), col.getFormulaString()));
                        }
                        col.forceNotNull();
                    }
                }
                propertyBinder.setLazy(lazy);
                propertyBinder.setColumns(columns);
                if (isOverridden) {
                    final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(isId, propertyHolder, property.getName(), context);
                    propertyBinder.setReferencedEntityName(mapsIdProperty.getClassOrElementName());
                }
                propertyBinder.makePropertyValueAndBind();
            }
            if (isOverridden) {
                final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(isId, propertyHolder, property.getName(), context);
                Map<String, IdentifierGeneratorDefinition> localGenerators = (HashMap<String, IdentifierGeneratorDefinition>) classGenerators.clone();
                final IdentifierGeneratorDefinition.Builder foreignGeneratorBuilder = new IdentifierGeneratorDefinition.Builder();
                foreignGeneratorBuilder.setName("Hibernate-local--foreign generator");
                foreignGeneratorBuilder.setStrategy("foreign");
                foreignGeneratorBuilder.addParam("property", mapsIdProperty.getPropertyName());
                final IdentifierGeneratorDefinition foreignGenerator = foreignGeneratorBuilder.build();
                localGenerators.put(foreignGenerator.getName(), foreignGenerator);
                BinderHelper.makeIdGenerator((SimpleValue) propertyBinder.getValue(), foreignGenerator.getStrategy(), foreignGenerator.getName(), context, localGenerators);
            }
            if (isId) {
                //components and regular basic types create SimpleValue objects
                final SimpleValue value = (SimpleValue) propertyBinder.getValue();
                if (!isOverridden) {
                    processId(propertyHolder, inferredData, value, classGenerators, isIdentifierMapper, context);
                }
            }
        }
    }
    //init index
    //process indexes afterQuery everything: in second pass, many to one has to be done beforeQuery indexes
    Index index = property.getAnnotation(Index.class);
    if (index != null) {
        if (joinColumns != null) {
            for (Ejb3Column column : joinColumns) {
                column.addIndex(index, inSecondPass);
            }
        } else {
            if (columns != null) {
                for (Ejb3Column column : columns) {
                    column.addIndex(index, inSecondPass);
                }
            }
        }
    }
    // Natural ID columns must reside in one single UniqueKey within the Table.
    // For now, simply ensure consistent naming.
    // TODO: AFAIK, there really isn't a reason for these UKs to be created
    // on the secondPass.  This whole area should go away...
    NaturalId naturalIdAnn = property.getAnnotation(NaturalId.class);
    if (naturalIdAnn != null) {
        if (joinColumns != null) {
            for (Ejb3Column column : joinColumns) {
                String keyName = "UK_" + Constraint.hashedName(column.getTable().getName() + "_NaturalID");
                column.addUniqueKey(keyName, inSecondPass);
            }
        } else {
            for (Ejb3Column column : columns) {
                String keyName = "UK_" + Constraint.hashedName(column.getTable().getName() + "_NaturalID");
                column.addUniqueKey(keyName, inSecondPass);
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) MapKeyJoinColumnDelegator(org.hibernate.cfg.annotations.MapKeyJoinColumnDelegator) Index(org.hibernate.annotations.Index) XClass(org.hibernate.annotations.common.reflection.XClass) ManyToOne(javax.persistence.ManyToOne) DiscriminatorFormula(org.hibernate.annotations.DiscriminatorFormula) Formula(org.hibernate.annotations.Formula) PrimaryKeyJoinColumn(javax.persistence.PrimaryKeyJoinColumn) MapKeyJoinColumn(javax.persistence.MapKeyJoinColumn) JoinColumn(javax.persistence.JoinColumn) AnnotationException(org.hibernate.AnnotationException) ElementCollection(javax.persistence.ElementCollection) NaturalId(org.hibernate.annotations.NaturalId) RootClass(org.hibernate.mapping.RootClass) OrderColumn(javax.persistence.OrderColumn) EmbeddedId(javax.persistence.EmbeddedId) ListIndexBase(org.hibernate.annotations.ListIndexBase) OneToMany(javax.persistence.OneToMany) CollectionId(org.hibernate.annotations.CollectionId) LazyGroup(org.hibernate.annotations.LazyGroup) MapsId(javax.persistence.MapsId) NaturalId(org.hibernate.annotations.NaturalId) EmbeddedId(javax.persistence.EmbeddedId) Id(javax.persistence.Id) CollectionId(org.hibernate.annotations.CollectionId) CollectionBinder(org.hibernate.cfg.annotations.CollectionBinder) OnDelete(org.hibernate.annotations.OnDelete) Cache(org.hibernate.annotations.Cache) NaturalIdCache(org.hibernate.annotations.NaturalIdCache) Basic(javax.persistence.Basic) MapsId(javax.persistence.MapsId) MapKeyJoinColumns(javax.persistence.MapKeyJoinColumns) OneToOne(javax.persistence.OneToOne) MapKeyColumn(javax.persistence.MapKeyColumn) OrderColumn(javax.persistence.OrderColumn) PrimaryKeyJoinColumn(javax.persistence.PrimaryKeyJoinColumn) MapKeyJoinColumn(javax.persistence.MapKeyJoinColumn) Column(javax.persistence.Column) DiscriminatorColumn(javax.persistence.DiscriminatorColumn) JoinColumn(javax.persistence.JoinColumn) PropertyBinder(org.hibernate.cfg.annotations.PropertyBinder) Property(org.hibernate.mapping.Property) XProperty(org.hibernate.annotations.common.reflection.XProperty) Cascade(org.hibernate.annotations.Cascade) XProperty(org.hibernate.annotations.common.reflection.XProperty) MapKeyJoinColumns(javax.persistence.MapKeyJoinColumns) Columns(org.hibernate.annotations.Columns) JoinColumns(javax.persistence.JoinColumns) PrimaryKeyJoinColumns(javax.persistence.PrimaryKeyJoinColumns) Join(org.hibernate.mapping.Join) ManyToMany(javax.persistence.ManyToMany) MapKeyColumnDelegator(org.hibernate.cfg.annotations.MapKeyColumnDelegator) UniqueConstraint(javax.persistence.UniqueConstraint) Constraint(org.hibernate.mapping.Constraint) SimpleValue(org.hibernate.mapping.SimpleValue) MapKeyJoinColumn(javax.persistence.MapKeyJoinColumn) IdentifierGeneratorDefinition(org.hibernate.boot.model.IdentifierGeneratorDefinition) NotFound(org.hibernate.annotations.NotFound) JoinTable(javax.persistence.JoinTable)

Aggregations

JoinTable (javax.persistence.JoinTable)28 JoinColumn (javax.persistence.JoinColumn)18 Test (org.junit.Test)9 Field (java.lang.reflect.Field)8 Method (java.lang.reflect.Method)8 ManyToMany (javax.persistence.ManyToMany)8 UniqueConstraint (javax.persistence.UniqueConstraint)7 ReflectUtil (org.eweb4j.util.ReflectUtil)7 MapKeyJoinColumn (javax.persistence.MapKeyJoinColumn)6 OneToMany (javax.persistence.OneToMany)6 DAOException (org.eweb4j.orm.dao.DAOException)6 PrimaryKeyJoinColumn (javax.persistence.PrimaryKeyJoinColumn)4 HashMap (java.util.HashMap)3 AssociationOverride (javax.persistence.AssociationOverride)3 CollectionTable (javax.persistence.CollectionTable)3 ElementCollection (javax.persistence.ElementCollection)3 ManyToOne (javax.persistence.ManyToOne)3 AnnotationException (org.hibernate.AnnotationException)3 XClass (org.hibernate.annotations.common.reflection.XClass)3 File (java.io.File)2