use of javax.persistence.OneToMany 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);
}
}
}
}
}
}
});
}
use of javax.persistence.OneToMany 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);
}
}
}
use of javax.persistence.OneToMany in project eweb4j-framework by laiweiwei.
the class DAOImpl method queryBySql.
public <T> Collection<T> queryBySql(final String sql) {
Class<T> mappingCls = null;
if (this.targetEntity == null)
mappingCls = (Class<T>) this.clazz;
else
mappingCls = (Class<T>) this.targetEntity;
List<T> result = null;
try {
if (Map.class.isAssignableFrom(mappingCls)) {
Connection con = ds.getConnection();
if (args != null && args.size() > 0) {
result = (List<T>) JdbcUtil.getListWithArgs(con, mappingCls, sql, args.toArray(new Object[] {}));
} else {
result = (List<T>) JdbcUtil.getList(con, mappingCls, sql);
}
} else {
if (args != null && args.size() > 0) {
result = (List<T>) DAOFactory.getSelectDAO(dsName).selectBySQL(mappingCls, sql, args.toArray(new Object[] {}));
} else {
result = (List<T>) DAOFactory.getSelectDAO(dsName).selectBySQL(mappingCls, sql);
}
}
//this.clear();
if (result != null && result.size() > 0) {
for (T t : result) {
// ToOne relation class cascade select
ReflectUtil ru = new ReflectUtil(t);
for (Field field : ru.getFields()) {
String f = field.getName();
OneToOne o2o = field.getAnnotation(OneToOne.class);
ManyToOne m2o = field.getAnnotation(ManyToOne.class);
OneToMany o2m = field.getAnnotation(OneToMany.class);
ManyToMany m2m = field.getAnnotation(ManyToMany.class);
FetchType fetchType = null;
boolean is2One = false;
if (o2o != null) {
fetchType = o2o.fetch();
is2One = true;
}
if (m2o != null) {
fetchType = m2o.fetch();
is2One = true;
}
if (o2m != null) {
fetchType = o2m.fetch();
}
if (m2m != null) {
fetchType = m2m.fetch();
}
if (fetchType == null)
continue;
String beanId = field.getType().getName();
if (!is2One)
beanId = ClassUtil.getGenericType(field).getName();
boolean isEntity = ORMConfigBeanCache.containsKey(beanId);
if (!isEntity)
continue;
if (unFetch.contains(f))
continue;
if (fetch.contains(f)) {
log.debug("cascade select -> " + t.getClass().getName() + "." + f);
DAOFactory.getCascadeDAO(dsName).select(t, f);
continue;
}
if (FetchType.LAZY.equals(fetchType))
continue;
log.debug("cascade select -> " + t.getClass().getName() + "." + f);
DAOFactory.getCascadeDAO(dsName).select(t, f);
}
}
}
return result;
} catch (Exception e) {
log.error("sql-->" + sql, e);
throw new DAOException(sql + " execute exception", e);
}
}
use of javax.persistence.OneToMany 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);
}
}
}
}
use of javax.persistence.OneToMany in project hibernate-orm by hibernate.
the class PersistentAttributesHelper method getTargetEntityClass.
public static CtClass getTargetEntityClass(CtClass managedCtClass, CtField persistentField) throws NotFoundException {
// get targetEntity defined in the annotation
try {
OneToOne oto = PersistentAttributesHelper.getAnnotation(persistentField, OneToOne.class);
OneToMany otm = PersistentAttributesHelper.getAnnotation(persistentField, OneToMany.class);
ManyToOne mto = PersistentAttributesHelper.getAnnotation(persistentField, ManyToOne.class);
ManyToMany mtm = PersistentAttributesHelper.getAnnotation(persistentField, ManyToMany.class);
Class<?> targetClass = null;
if (oto != null) {
targetClass = oto.targetEntity();
}
if (otm != null) {
targetClass = otm.targetEntity();
}
if (mto != null) {
targetClass = mto.targetEntity();
}
if (mtm != null) {
targetClass = mtm.targetEntity();
}
if (targetClass != null && targetClass != void.class) {
return managedCtClass.getClassPool().get(targetClass.getName());
}
} catch (NotFoundException ignore) {
}
// infer targetEntity from generic type signature
String inferredTypeName = inferTypeName(managedCtClass, persistentField.getName());
return inferredTypeName == null ? null : managedCtClass.getClassPool().get(inferredTypeName);
}
Aggregations