<aside> 👉 Ejb3Column 클래스에서 @Column의 동작을 구현한다.

</aside>

public class Ejb3Column {

public static Ejb3Column[] buildColumnFromAnnotation(
			javax.persistence.Column[] anns,
			org.hibernate.annotations.Formula formulaAnn,
			Comment commentAnn,
			Nullability nullability,
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			String suffixForDefaultColumnName,
			Map<String, Join> secondaryTables,
			MetadataBuildingContext context) {
		Ejb3Column[] columns;
		if ( formulaAnn != null ) {
			Ejb3Column formulaColumn = new Ejb3Column();
			formulaColumn.setFormula( formulaAnn.value() );
			formulaColumn.setImplicit( false );
			formulaColumn.setBuildingContext( context );
			formulaColumn.setPropertyHolder( propertyHolder );
			formulaColumn.bind();
			columns = new Ejb3Column[] { formulaColumn };
		}
		else {
			javax.persistence.Column[] actualCols = anns;
			javax.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(
					StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
			);
			if ( overriddenCols != null ) {
				//check for overridden first
				if ( anns != null && overriddenCols.length != anns.length ) {
					throw new AnnotationException( "AttributeOverride.column() should override all columns for now" );
				}
				actualCols = overriddenCols.length == 0 ? null : overriddenCols;
				LOG.debugf( "Column(s) overridden for property %s", inferredData.getPropertyName() );
			}
			if ( actualCols == null ) {
				columns = buildImplicitColumn(
						inferredData,
						suffixForDefaultColumnName,
						secondaryTables,
						propertyHolder,
						commentAnn,
						nullability,
						context
				);
			}
			else {
				final int length = actualCols.length;
				columns = new Ejb3Column[length];
				for (int index = 0; index < length; index++) {

					final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
					final Database database = context.getMetadataCollector().getDatabase();
					final ImplicitNamingStrategy implicitNamingStrategy = context.getBuildingOptions().getImplicitNamingStrategy();
					final PhysicalNamingStrategy physicalNamingStrategy = context.getBuildingOptions().getPhysicalNamingStrategy();

					// 여기를 보면 column을 정의하고 있다.
					javax.persistence.Column col = actualCols[index];

					final String sqlType;
					// columnDefinition을 내가 적어준대로 동작하도록 하는 코드이다. sql의 Type을 치환시키는 코드에서 사용된다.
					if ( col.columnDefinition().isEmpty() ) {
						sqlType = null;
					}
					else {
						sqlType = normalizer.applyGlobalQuoting( col.columnDefinition() );
					}

					final String tableName;
					if ( StringHelper.isEmpty( col.table() ) ) {
						tableName = "";
					}
					else {
						tableName = database.getJdbcEnvironment()
								.getIdentifierHelper()
								.toIdentifier( col.table() )
								.render();
//						final Identifier logicalName = database.getJdbcEnvironment()
//								.getIdentifierHelper()
//								.toIdentifier( col.table() );
//						final Identifier physicalName = physicalNamingStrategy.toPhysicalTableName( logicalName );
//						tableName = physicalName.render( database.getDialect() );
					}

					final String columnName;
					if ( col.name() != null && col.name().isEmpty() ) {
						columnName = null;
					}
					else {
						// NOTE : this is the logical column name, not the physical!
						columnName = database.getJdbcEnvironment()
								.getIdentifierHelper()
								.toIdentifier( col.name() )
								.render();
					}

					Ejb3Column column = new Ejb3Column();

					if ( length == 1 ) {
						applyColumnDefault( column, inferredData );
					}

					column.setImplicit( false );
					column.setSqlType( sqlType );
					column.setLength( col.length() );
					column.setPrecision( col.precision() );
					column.setScale( col.scale() );
					if ( StringHelper.isEmpty( columnName ) && ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
						column.setLogicalColumnName( inferredData.getPropertyName() + suffixForDefaultColumnName );
					}
					else {
						column.setLogicalColumnName( columnName );
					}

					column.setPropertyName(
							BinderHelper.getRelativePath( propertyHolder, inferredData.getPropertyName() )
					);
					column.setNullable(
						col.nullable()
					); //TODO force to not null if available? This is a (bad) user choice.
					if ( commentAnn != null ) {
						column.setComment( commentAnn.value() );
					}
					column.setUnique( col.unique() );
					column.setInsertable( col.insertable() );
					column.setUpdatable( col.updatable() );
					column.setExplicitTableName( tableName );
					column.setPropertyHolder( propertyHolder );
					column.setJoins( secondaryTables );
					column.setBuildingContext( context );
					column.extractDataFromPropertyData(inferredData);
					column.bind();
					columns[index] = column;
				}
			}
		}
		return columns;
	}
}