/** * 一対多の関連を処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ * @param oneToMany 一対多関連 */ protected void doOneToMany( PropertyMeta propertyMeta, Field field, EntityMeta entityMeta, OneToMany oneToMany) { propertyMeta.setRelationshipType(RelationshipType.ONE_TO_MANY); if (!List.class.isAssignableFrom(field.getType())) { throw new OneToManyNotListRuntimeException(entityMeta.getName(), propertyMeta.getName()); } Class<?> relationshipClass = ReflectionUtil.getElementTypeOfList(field.getGenericType()); if (relationshipClass == null) { throw new OneToManyNotGenericsRuntimeException(entityMeta.getName(), propertyMeta.getName()); } if (relationshipClass.getAnnotation(Entity.class) == null) { throw new RelationshipNotEntityRuntimeException( entityMeta.getName(), propertyMeta.getName(), relationshipClass); } propertyMeta.setRelationshipClass(relationshipClass); String mappedBy = oneToMany.mappedBy(); if (!StringUtil.isEmpty(mappedBy)) { if (propertyMeta.getJoinColumnMetaList().size() > 0) { throw new BothMappedByAndJoinColumnRuntimeException( entityMeta.getName(), propertyMeta.getName()); } propertyMeta.setMappedBy(mappedBy); } else { throw new MappedByMandatoryRuntimeException(entityMeta.getName(), propertyMeta.getName()); } }
/** * 識別子メタデータを処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ */ protected void doId(PropertyMeta propertyMeta, Field field, EntityMeta entityMeta) { propertyMeta.setId(field.getAnnotation(Id.class) != null); GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class); if (generatedValue == null) { return; } GenerationType generationType = generatedValue.strategy(); propertyMeta.setGenerationType(generationType); switch (generationType) { case AUTO: doIdentityIdGenerator(propertyMeta, entityMeta); doSequenceIdGenerator(propertyMeta, generatedValue, entityMeta); doTableIdGenerator(propertyMeta, generatedValue, entityMeta); break; case IDENTITY: doIdentityIdGenerator(propertyMeta, entityMeta); break; case SEQUENCE: if (!doSequenceIdGenerator(propertyMeta, generatedValue, entityMeta)) { throw new IdGeneratorNotFoundRuntimeException( entityMeta.getName(), propertyMeta.getName(), generatedValue.generator()); } break; case TABLE: if (!doTableIdGenerator(propertyMeta, generatedValue, entityMeta)) { throw new IdGeneratorNotFoundRuntimeException( entityMeta.getName(), propertyMeta.getName(), generatedValue.generator()); } break; } }
/** * テーブルを処理します。 * * @param entityMeta エンティティメタデータ * @param propertyMeta プロパティメタデータ * @param foreignKeyDesc 外部キー記述 */ protected void doTable( EntityMeta entityMeta, PropertyMeta propertyMeta, ForeignKeyDesc foreignKeyDesc) { EntityMeta inverseEntityMeta = entityMetaFactory.getEntityMeta(propertyMeta.getRelationshipClass()); TableMeta tableMeta = inverseEntityMeta.getTableMeta(); foreignKeyDesc.setReferencedCatalogName(tableMeta.getCatalog()); foreignKeyDesc.setReferencedSchemaName(tableMeta.getSchema()); foreignKeyDesc.setReferencedTableName(tableMeta.getName()); foreignKeyDesc.setReferencedFullTableName(tableMeta.getFullName()); }
/** * 外部キー記述を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param table テーブル */ protected void doForeignKeyDesc(EntityMeta entityMeta, TableDesc tableDesc, Table table) { for (int i = 0; i < entityMeta.getPropertyMetaSize(); i++) { PropertyMeta propertyMeta = entityMeta.getPropertyMeta(i); ForeignKeyDesc foreignKeyDesc = foreignKeyDescFactory.getForeignKeyDesc(entityMeta, propertyMeta); if (foreignKeyDesc != null) { tableDesc.addForeignKeyDesc(foreignKeyDesc); } } }
/** * カラム記述を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param table テーブル */ protected void doColumnDesc(EntityMeta entityMeta, final TableDesc tableDesc, Table table) { List<ColumnDescRef> columnDescRefList = new ArrayList<ColumnDescRef>(); for (int i = 0; i < entityMeta.getColumnPropertyMetaSize(); i++) { PropertyMeta propertyMeta = entityMeta.getColumnPropertyMeta(i); ColumnDesc columnDesc = columnDescFactory.getColumnDesc(entityMeta, propertyMeta); if (columnDesc != null) { columnDescRefList.add(new ColumnDescRef(i, columnDesc)); } } Collections.sort(columnDescRefList, createColumnDescRefComparator(tableDesc)); for (ColumnDescRef columnDescRef : columnDescRefList) { tableDesc.addColumnDesc(columnDescRef.columnDesc); } }
/** * 識別子生成用のテーブル記述を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param table テーブル */ protected void doIdTableDesc(EntityMeta entityMeta, TableDesc tableDesc, Table table) { for (PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) { TableDesc idTableDesc = idTableDescFactory.getTableDesc(entityMeta, propertyMeta); if (idTableDesc == null) { continue; } tableDesc.addIdTableDesc(idTableDesc); String fullName = idTableDesc.getFullName().toLowerCase(); TableDesc cache = tableDescMap.get(fullName); if (cache == null) { tableDescMap.put(fullName, idTableDesc); } else { cache.setCatalogName(idTableDesc.getCatalogName()); cache.setSchemaName(idTableDesc.getSchemaName()); cache.setName(idTableDesc.getName()); cache.setPrimaryKeyDesc(idTableDesc.getPrimaryKeyDesc()); for (ColumnDesc columnDesc : idTableDesc.getColumnDescList()) { cache.addColumnDesc(columnDesc); } for (UniqueKeyDesc uniqueKeyDesc : idTableDesc.getUniqueKeyDescList()) { cache.addUniqueKeyDesc(uniqueKeyDesc); } } } }
/** * 名前を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param table テーブル */ protected void doName(EntityMeta entityMeta, TableDesc tableDesc, Table table) { TableMeta tableMeta = entityMeta.getTableMeta(); tableDesc.setCatalogName(tableMeta.getCatalog()); tableDesc.setSchemaName(tableMeta.getSchema()); tableDesc.setName(tableMeta.getName()); tableDesc.setCanonicalName(buildCanonicalName(tableMeta)); }
/** * シーケンスの名前を返します。 * * @param entityMeta エンティティメタデータ * @param propertyMeta プロパティメタデータ * @param sequenceGenerator シーケンスジェネレータ * @return シーケンスの名前 */ protected String getSequenceName( EntityMeta entityMeta, PropertyMeta propertyMeta, SequenceGenerator sequenceGenerator) { String sequenceName = sequenceGenerator.sequenceName(); if (!StringUtil.isEmpty(sequenceName)) { return sequenceName; } return entityMeta.getTableMeta().getName() + "_" + propertyMeta.getColumnMeta().getName(); }
/** * シーケンス記述を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param table テーブル */ protected void doSequenceDesc(EntityMeta entityMeta, TableDesc tableDesc, Table table) { for (PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) { SequenceDesc sequenceDesc = sequenceDescFactory.getSequenceDesc(entityMeta, propertyMeta); if (sequenceDesc != null) { tableDesc.addSequenceDesc(sequenceDesc); } } }
/** * 一対一の関連を処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ * @param oneToOne 一対一関連 */ protected void doOneToOne( PropertyMeta propertyMeta, Field field, EntityMeta entityMeta, OneToOne oneToOne) { propertyMeta.setRelationshipType(RelationshipType.ONE_TO_ONE); Class<?> relationshipClass = field.getType(); if (relationshipClass.getAnnotation(Entity.class) == null) { throw new RelationshipNotEntityRuntimeException( entityMeta.getName(), propertyMeta.getName(), relationshipClass); } propertyMeta.setRelationshipClass(relationshipClass); String mappedBy = oneToOne.mappedBy(); if (!StringUtil.isEmpty(mappedBy)) { if (propertyMeta.getJoinColumnMetaList().size() > 0) { throw new BothMappedByAndJoinColumnRuntimeException( entityMeta.getName(), propertyMeta.getName()); } propertyMeta.setMappedBy(mappedBy); } }
/** * 名前を処理します。 * * @param entityMeta エンティティメタデータ * @param tableDesc テーブル記述 * @param generator テーブルジェネレータ */ protected void doName(EntityMeta entityMeta, TableDesc tableDesc, TableGenerator generator) { String catalog = generator.catalog(); if (StringUtil.isEmpty(catalog)) { catalog = entityMeta.getTableMeta().getCatalog(); } String schema = generator.schema(); if (StringUtil.isEmpty(schema)) { schema = entityMeta.getTableMeta().getSchema(); } String name = generator.table(); if (StringUtil.isEmpty(name)) { name = TableIdGenerator.DEFAULT_TABLE; } tableDesc.setCatalogName(catalog); tableDesc.setSchemaName(schema); tableDesc.setName(name); tableDesc.setCanonicalName(buildCanonicalName(catalog, schema, name)); }
public TableDesc getTableDesc(EntityMeta entityMeta) { String fullName = entityMeta.getTableMeta().getFullName().toLowerCase(); TableDesc tableDesc = tableDescMap.get(fullName); if (tableDesc != null) { return tableDesc; } tableDesc = createTableDesc(entityMeta); tableDescMap.put(fullName, tableDesc); return tableDesc; }
/** * フェッチタイプを処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ */ protected void doFetchType( final PropertyMeta propertyMeta, final Field field, final EntityMeta entityMeta) { final Basic basic = field.getAnnotation(Basic.class); if (basic == null) { propertyMeta.setFetchType(FetchType.EAGER); return; } if (propertyMeta.isId() && basic.fetch() == FetchType.LAZY) { throw new LazyFetchSpecifiedRuntimeException(entityMeta.getName(), propertyMeta.getName()); } propertyMeta.setFetchType(basic.fetch()); }
/** * 時制の種別を処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ */ protected void doTemporal(PropertyMeta propertyMeta, Field field, EntityMeta entityMeta) { if (propertyMeta.getPropertyClass() != java.util.Date.class && propertyMeta.getPropertyClass() != Calendar.class) { return; } Temporal temporal = field.getAnnotation(Temporal.class); if (temporal == null) { throw new TemporalTypeNotSpecifiedRuntimeException( entityMeta.getName(), propertyMeta.getName()); } propertyMeta.setTemporalType(temporal.value()); }
/** * 関連用のクラスを返します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ * @return 関連用のクラス * @throws OneToManyNotGenericsRuntimeException 一対多の関連がジェネリクスのリストではない場合。 */ protected Class<?> getRelationshipClass( PropertyMeta propertyMeta, Field field, EntityMeta entityMeta) throws OneToManyNotGenericsRuntimeException { Class<?> clazz = field.getType(); if (List.class.isAssignableFrom(clazz)) { clazz = ReflectionUtil.getElementTypeOfList(field.getGenericType()); if (clazz == null) { throw new OneToManyNotGenericsRuntimeException( entityMeta.getName(), propertyMeta.getName()); } } return clazz; }
/** * 多対一の関連を処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ * @param manyToOne 多対一関連 */ protected void doManyToOne( PropertyMeta propertyMeta, Field field, EntityMeta entityMeta, @SuppressWarnings("unused") ManyToOne manyToOne) { propertyMeta.setRelationshipType(RelationshipType.MANY_TO_ONE); Class<?> relationshipClass = field.getType(); if (relationshipClass.getAnnotation(Entity.class) == null) { throw new RelationshipNotEntityRuntimeException( entityMeta.getName(), propertyMeta.getName(), relationshipClass); } propertyMeta.setRelationshipClass(relationshipClass); }
/** * 関連を処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ * @param annotation 関連のアノテーション */ protected void doRelationship( PropertyMeta propertyMeta, Field field, EntityMeta entityMeta, Object annotation) { doJoinColumn(propertyMeta, field, entityMeta); if (OneToOne.class.isInstance(annotation)) { doOneToOne(propertyMeta, field, entityMeta, OneToOne.class.cast(annotation)); } else if (OneToMany.class.isInstance(annotation)) { doOneToMany(propertyMeta, field, entityMeta, OneToMany.class.cast(annotation)); } else if (ManyToOne.class.isInstance(annotation)) { doManyToOne(propertyMeta, field, entityMeta, ManyToOne.class.cast(annotation)); } else { throw new UnsupportedRelationshipRuntimeException( entityMeta.getName(), propertyMeta.getName()); } }
/** * バージョンチェック用かどうかを処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ */ protected void doVersion( PropertyMeta propertyMeta, Field field, @SuppressWarnings("unused") EntityMeta entityMeta) { if (field.getAnnotation(Version.class) == null) { return; } Class<?> clazz = ClassUtil.getWrapperClassIfPrimitive(field.getType()); if (clazz != Integer.class && clazz != Long.class && clazz != int.class && clazz != long.class) { throw new VersionPropertyNotNumberRuntimeException( entityMeta.getName(), propertyMeta.getName()); } propertyMeta.setVersion(true); }
/** * {@link GenerationType#TABLE}方式で識別子の値を自動生成するIDジェネレータを処理します。 * * @param propertyMeta プロパティメタデータ * @param generatedValue 識別子に付けられた{@link GeneratedValue}アノテーション * @param entityMeta エンティティのメタデータ * @return {@link GenerationType#TABLE}方式で識別子の値を自動生成するIDジェネレータが存在した場合に <code>true</code> */ protected boolean doTableIdGenerator( PropertyMeta propertyMeta, GeneratedValue generatedValue, EntityMeta entityMeta) { String name = generatedValue.generator(); TableGenerator tableGenerator; if (StringUtil.isEmpty(name)) { tableGenerator = DEFAULT_TABLE_GENERATOR; } else { tableGenerator = propertyMeta.getField().getAnnotation(TableGenerator.class); if (tableGenerator == null || !name.equals(tableGenerator.name())) { tableGenerator = entityMeta.getEntityClass().getAnnotation(TableGenerator.class); if (tableGenerator == null || !name.equals(tableGenerator.name())) { return false; } } } propertyMeta.setTableIdGenerator( new TableIdGenerator(entityMeta, propertyMeta, tableGenerator)); return true; }
/** * {@link GenerationType#SEQUENCE}方式で識別子の値を自動生成するIDジェネレータを処理します。 * * @param propertyMeta プロパティメタデータ * @param generatedValue 識別子に付けられた{@link GeneratedValue}アノテーション * @param entityMeta エンティティのメタデータ * @return {@link GenerationType#SEQUENCE}方式で識別子の値を自動生成するIDジェネレータが存在した場合に <code>true</code> */ protected boolean doSequenceIdGenerator( PropertyMeta propertyMeta, GeneratedValue generatedValue, EntityMeta entityMeta) { String name = generatedValue.generator(); SequenceGenerator sequenceGenerator; if (StringUtil.isEmpty(name)) { sequenceGenerator = DEFAULT_SEQUENCE_GENERATOR; } else { sequenceGenerator = propertyMeta.getField().getAnnotation(SequenceGenerator.class); if (sequenceGenerator == null || !name.equals(sequenceGenerator.name())) { sequenceGenerator = entityMeta.getEntityClass().getAnnotation(SequenceGenerator.class); if (sequenceGenerator == null || !name.equals(sequenceGenerator.name())) { return false; } } } propertyMeta.setSequenceIdGenerator( new SequenceIdGenerator(entityMeta, propertyMeta, sequenceGenerator)); return true; }
/** * テーブルジェネレータを返します。 * * @param entityMeta エンティティメタデータ * @param propertyMeta プロパティメタデータ * @return テーブルジェネレータ */ protected TableGenerator getTableGenerator(EntityMeta entityMeta, PropertyMeta propertyMeta) { Field field = propertyMeta.getField(); GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class); if (generatedValue == null) { throw new IllegalStateException("@GeneratedValue not found."); } String name = generatedValue.generator(); if (StringUtil.isEmpty(name)) { return AnnotationUtil.getDefaultTableGenerator(); } TableGenerator tableGenerator = field.getAnnotation(TableGenerator.class); if (tableGenerator != null && name.equals(tableGenerator.name())) { return tableGenerator; } tableGenerator = entityMeta.getEntityClass().getAnnotation(TableGenerator.class); if (tableGenerator != null && name.equals(tableGenerator.name())) { return tableGenerator; } throw new IllegalStateException("@TableGenerator not found."); }
public SequenceDesc getSequenceDesc(EntityMeta entityMeta, PropertyMeta propertyMeta) { GenerationType generationType = propertyMeta.getGenerationType(); if (generationType == GenerationType.AUTO) { generationType = dialect.getDefaultGenerationType(); } if (generationType == GenerationType.SEQUENCE) { if (!dialect.supportsSequence()) { throw new UnsupportedGenerationTypeRuntimeException( GenerationType.SEQUENCE, entityMeta.getName(), propertyMeta.getName()); } SequenceGenerator generator = getSequenceGenerator(entityMeta, propertyMeta); SequenceDesc sequenceDesc = new SequenceDesc(); String sequenceName = getSequenceName(entityMeta, propertyMeta, generator); sequenceDesc.setSequenceName(sequenceName); sequenceDesc.setInitialValue(generator.initialValue()); sequenceDesc.setAllocationSize(generator.allocationSize()); sequenceDesc.setDataType(getDataType(propertyMeta)); return sequenceDesc; } return null; }
/** * JoinColumnを処理します。 * * @param propertyMeta プロパティメタデータ * @param field フィールド * @param entityMeta エンティティメタデータ */ protected void doJoinColumn(PropertyMeta propertyMeta, Field field, EntityMeta entityMeta) { JoinColumn joinColumn = field.getAnnotation(JoinColumn.class); if (joinColumn != null) { JoinColumnMeta meta = new JoinColumnMeta(joinColumn.name(), joinColumn.referencedColumnName()); propertyMeta.addJoinColumnMeta(meta); } else { JoinColumns joinColumns = field.getAnnotation(JoinColumns.class); if (joinColumns != null) { JoinColumn[] array = joinColumns.value(); for (int i = 0; i < array.length; i++) { JoinColumn jc = array[i]; JoinColumnMeta meta = new JoinColumnMeta(jc.name(), jc.referencedColumnName()); if (i > 0 && (meta.getName() == null || meta.getReferencedColumnName() == null)) { throw new JoinColumnNameAndReferencedColumnNameMandatoryRuntimeException( entityMeta.getName(), propertyMeta.getName(), i + 1); } propertyMeta.addJoinColumnMeta(meta); } } } }
/** * テーブルを取得します。 * * @param entityMeta エンティティメタデータ * @return テーブル */ protected Table getTable(EntityMeta entityMeta) { Class<?> clazz = entityMeta.getEntityClass(); Table table = clazz.getAnnotation(Table.class); return table != null ? table : AnnotationUtil.getDefaultTable(); }
/** * {@link ValueType}を処理します。 * * @param propertyMeta プロパティメタデータ * @param entityMeta エンティティメタデータ */ @SuppressWarnings("unchecked") protected void doValueType(final PropertyMeta propertyMeta, final EntityMeta entityMeta) { final Class<?> propertyClass = propertyMeta.getPropertyClass(); final ValueType valueType = valueTypes.get(propertyClass); if (valueType != null) { propertyMeta.setValueType(valueType); return; } if (propertyClass == String.class) { if (propertyMeta.isLob()) { propertyMeta.setValueType(ValueTypes.CLOB); } else { propertyMeta.setValueType(ValueTypes.STRING); } return; } if (propertyClass == byte[].class) { if (propertyMeta.isLob()) { propertyMeta.setValueType(ValueTypes.BLOB); } else { propertyMeta.setValueType(ValueTypes.BYTE_ARRAY); } return; } if (propertyClass == Date.class) { switch (propertyMeta.getTemporalType()) { case DATE: propertyMeta.setValueType(ValueTypes.DATE_SQLDATE); return; case TIME: propertyMeta.setValueType(ValueTypes.DATE_TIME); return; case TIMESTAMP: propertyMeta.setValueType(ValueTypes.DATE_TIMESTAMP); return; } } if (propertyClass == Calendar.class) { switch (propertyMeta.getTemporalType()) { case DATE: propertyMeta.setValueType(ValueTypes.CALENDAR_SQLDATE); return; case TIME: propertyMeta.setValueType(ValueTypes.CALENDAR_TIME); return; case TIMESTAMP: propertyMeta.setValueType(ValueTypes.CALENDAR_TIMESTAMP); return; } } if (propertyClass.isEnum()) { if (propertyMeta.getEnumType() == null) { propertyMeta.setValueType(ValueTypes.getValueType(propertyClass)); return; } switch (propertyMeta.getEnumType()) { case ORDINAL: propertyMeta.setValueType(ValueTypes.getEnumOrdinalValueType(propertyClass)); return; case STRING: propertyMeta.setValueType(ValueTypes.getEnumStringValueType(propertyClass)); return; } } final ValueType userDefinedValueType = ValueTypes.createUserDefineValueType(propertyClass); if (userDefinedValueType != null) { propertyMeta.setValueType(userDefinedValueType); return; } if (Serializable.class.isAssignableFrom(propertyClass)) { if (propertyMeta.isLob()) { propertyMeta.setValueType(ValueTypes.SERIALIZABLE_BLOB); } else { propertyMeta.setValueType(ValueTypes.SERIALIZABLE_BYTE_ARRAY); } return; } throw new UnsupportedPropertyTypeRuntimeException( entityMeta.getName(), propertyMeta.getName(), propertyMeta.getPropertyClass()); }