<%#
 Copyright 2013-2024 the original author or authors from the JHipster project.

 This file is part of the JHipster project, see https://www.jhipster.tech/
 for more information.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-%>
<%#
 This is a fragment file, it will be merged into to root template if available.
 EJS fragments will process % delimiter tags in template and & delimiter tags in the merge process.
-%>
<&_ if (fragment.importSection) { -&>
import org.hibernate.annotations.JoinFormula;
import org.hibernate.annotations.SQLRestriction;
import org.hibernate.annotations.SQLJoinTableRestriction;
  <%_ if (ormTool === 'hibernate') { _%>
    <%_ if (softDelete) { _%>
import org.hibernate.annotations.SoftDelete;
import org.hibernate.annotations.SoftDeleteType;
import org.hibernate.type.NumericBooleanConverter;
    <%_ } _%>
import <%= javaVersion === '17' ? 'jakarta' : 'javax'%>.persistence.*;
import <%= javaVersion === '17' ? 'jakarta' : 'javax'%>.persistence.CascadeType;
  <%_ } _%>
<%_ if (((prodDatabaseTypePostgresql && anyFieldHasTextContentType) || (anyFieldIsUUID && (prodDatabaseTypeMysql || prodDatabaseTypeMariadb))) && ormTool === 'hibernate') { _%><%# modify by begcode _%>
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
<%_ } _%>
<%_ if (ormTool === 'mybatis') { _%>
import com.baomidou.mybatisplus.annotation.*;
  <%_ if (relationships && relationships.length > 0) { _%>
import com.diboot.core.binding.annotation.*;
  <%_ } _%>
<%_ } _%>
<&_ } -&>

<&_ if (fragment.annotationSection) { -&>
<%_ if (ormTool === 'hibernate') { _%>
@Entity
@Table(name = "<%= entityTableName %>")
  <%_ if (softDelete) { _%>
@SoftDelete(strategy = SoftDeleteType.DELETED, columnName = "del_flag", converter = NumericBooleanConverter.class)
  <%_ } _%>
<%_ } else { _%>
@TableName(value = "<%= entityTableName %>")
  <%_ if (!isUsingMapsId && primaryKey.fields[0].jpaGeneratedValue === 'sequence') { _%>
@KeySequence(value = "sequence_generator")
  <%_ } _%>
<%_ } _%>
<&_ } -&>

<%_ for (const field of fields) { -%>
<&_ if (fragment.field<%- field.fieldNameCapitalized %>AnnotationSection) { -&>
  <%_ if (field.id && ormTool === 'hibernate') { _%>
    @Id
    <%_ if (field.jpaGeneratedValue === 'identity') { _%>
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    <%_ } else if (field.jpaGeneratedValue === 'sequence') { _%>
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator"<% if (field.liquibaseCustomSequenceGenerator) { %>, sequenceName = "<%- field.jpaSequenceGeneratorName %>"<% } %>)
    <%_ } else if (field.jpaGeneratedValue) { _%>
    @GeneratedValue
    <%_ } _%>
  <%_ } _%>
  <%_ if (field.id && ormTool === 'mybatis') { _%>
    <%_ if (isUsingMapsId || primaryKey.fields[0].jpaGeneratedValue === 'sequence') { _%>
    @TableId(value = "id", type = IdType.INPUT)
    <%_ } else { _%>
      <%_ if (field.fieldType === 'String') { _%>
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
      <%_ } else if (field.fieldType === 'UUID') { _%>
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
      <% } else { %>
    @TableId(value = "id", type = IdType.AUTO)
      <%_ } _%>
    <%_ } _%>
  <%_ } _%>
  <%_ if (ormTool === 'hibernate') { _%>
  <%_ if (field.fieldIsEnum) { _%>
    @Enumerated(EnumType.STRING)
  <%_ } _%>
  <%_ if (field.fieldTypeBytes) { _%>
    @Lob
  <%_ } _%>
  <%_ if (field.fieldTypeTemporal || field.fieldTypeDuration) { _%>
    @Column(name = "<%- field.fieldNameAsDatabaseColumn %>"<% if (field.fieldValidationRequired) { %>, nullable = false<% } %><% if (field.fieldValidationUnique) { %>, unique = true<% } %>)
  <%_ } else if (field.fieldTypeBigDecimal) { _%>
    @Column(name = "<%- field.fieldNameAsDatabaseColumn %>", precision = 21, scale = 2<% if (field.fieldValidationRequired) { %>, nullable = false<% } %><% if (field.fieldValidationUnique) { %>, unique = true<% } %>)
  <%_ } else if (field.fieldTypeUUID && (prodDatabaseTypeMysql || prodDatabaseTypeMariadb)) { _%>
    @JdbcTypeCode(SqlTypes.VARCHAR)
    @Column(name = "<%- field.fieldNameAsDatabaseColumn %>", length = 36<% if (field.fieldValidationRequired) { %>, nullable = false<% } %><% if (field.fieldValidationUnique) { %>, unique = true<% } %>)
  <%_ } else { _%>
    @Column(name = "<%- field.fieldNameAsDatabaseColumn %>"<% if (field.options?.ownerEntityName || field.options?.ownerEntityId || softDelete && !skipSoftDelete && field.options?.logicDelete) { %>, insertable = false, updatable = false<% } %><% if (field.fieldValidate === true) { %><% if (field.fieldValidationMaxLength) { %>, length = <%= field.fieldValidateRulesMaxlength %><% } %><% if (field.fieldValidationRequired) { %>, nullable = false<% } %><% if (field.fieldValidationUnique) { %>, unique = true<% } %><% } %>)
  <%_ } _%>
  <%_ } else { _%>
    <%_ if (!field.id) { _%>
    @TableField(value = "<%- (field.options?.fieldColumnName) || field.fieldNameAsDatabaseColumn %>"<% if (field.fieldType !== 'byte[]' && field.fieldType.indexOf('[]') !== -1) { %>, typeHandler = org.apache.ibatis.type.ArrayTypeHandler.class<% } %><% if (['Instant', 'ZonedDateTime', 'LocalDate', 'Duration'].includes(field.fieldType) && field.options?.createdDate || (['Long'].includes(field.fieldType) && field.options?.createdById) || (['String'].includes(field.fieldType) && field.options?.createdByLogin || softDelete && !skipSoftDelete && field.options?.logicDelete)) { %>, fill = FieldFill.INSERT<% } %><% if (['Instant', 'ZonedDateTime', 'LocalDate', 'Duration'].includes(field.fieldType) && field.options?.lastModifiedDate || (['Long'].includes(field.fieldType) && field.options?.lastModifiedById) || (['String'].includes(field.fieldType) && field.options?.lastModifiedByLogin)) { %>, fill = FieldFill.INSERT_UPDATE<% } %>)
    <%_ } _%>
    <%_ if (softDelete && !skipSoftDelete && field.options?.logicDelete) { _%>
    @TableLogic
    <%_ } _%>
  <%_ } _%>
<&_ } -&>
<%_ } -%>

<%_ for (const field of fields.filter(field => field.fieldWithContentType)) { -%>
<&_ if (fragment.field<%- field.fieldNameCapitalized %>ContentTypeAnnotationSection) { -&>
    <%_ if (ormTool === 'hibernate') { _%>
    @Column(
        name = "<%- field.fieldNameAsDatabaseColumn %>_content_type"
        <%_ if (field.fieldValidationRequired) { %>, nullable = false<% } _%>
    )
   <%_ } else { _%>
    @TableField(value = "<%- field.fieldNameAsDatabaseColumn %>_content_type")
   <%_ } _%>
<&_ } -&>
<%_ } -%>

<%_ for (const relationship of relationships) { -%>
<&_ if (fragment.relationship<%- relationship.relationshipNameCapitalized %>AnnotationSection) { -&>
  <%_ if (relationship.relationshipOneToMany) { -%>
    <%_ if (ormTool === 'hibernate') { _%>
    @OneToMany(fetch = FetchType.LAZY<% if (!relationship.bcConfig.leftRelateByIdEntity) { %>, mappedBy = "<%= relationship.otherEntityRelationshipName %>"<% } else { %>, orphanRemoval = true, cascade = CascadeType.ALL<% } %>)
      <% if (relationship.bcConfig.leftRelateByIdEntity) { %>
    @SQLRestriction("owner_entity_name = '<%= persistClass %>'")
    @JoinColumn(name = "owner_entity_id", referencedColumnName = "<%= primaryKey.name %>")
      <%_ } _%>
    <%_ } else { _%>
    @TableField(exist = false)
        <%_ if (relationship.source?.annotationOnSource?.includes('countByPrimaryKey') && relationship.source?.annotationOnSource?.includes('unidirectional')) { _%>
    @BindCount(
        entity = <%= relationship.otherEntity.persistClass %>.class,<% const otherEntitySortFields = relationship.otherEntity.fields.filter(field => field.options?.sortField); %>
        condition = "id=<% if (relationship.options?.source?.annotationOnSource?.includes('relateByIdEntity')) { %>owner_entity_id AND owner_entity_name = '<%= persistClass %>' <% } else { %><%= relationship.otherRelationship.columnName %>_id<% } %>"
    )
        <%_ } else { _%>
    @BindEntityList(
        entity = <%= relationship.otherEntity.persistClass %>.class<% if ((fieldsContainParentAndChildren && relationship.relationshipName === 'children') || relationship.relationshipOneToMany && relationship.source?.annotationOnSource?.includes('unidirectional')) { %>,
        deepBind = true
        <% } %>,<% const otherEntitySortFields = relationship.otherEntity.fields.filter(field => field.options?.sortField); %>
        condition = "id=<% if (relationship.options?.source?.annotationOnSource?.includes('relateByIdEntity')) { %>owner_entity_id AND owner_entity_name = '<%= persistClass %>' <% } else { %><%= relationship.otherRelationship.columnName %>_id<% } %>"<% if (otherEntitySortFields && otherEntitySortFields.length) { %>,
        orderBy = "<%= otherEntitySortFields.map(otherEntitySortField => `${otherEntitySortField.fieldName}:${otherEntitySortField.options?.sortField === 'asc' ? 'ASC' : 'DESC'}`).join(',') %>"
        <%_ } _%>
    )
        <%_ } %>
    <%_ } %>
  <%_ } else if (relationship.relationshipManyToOne) { -%>
    <%_ if (ormTool === 'hibernate') { _%>
    @ManyToOne(<% if (relationship.relationshipRequired) { %>optional = false<% } else { %>fetch = <% if (softDelete) { %>FetchType.EAGER<% } else { %>FetchType.LAZY<% } %><% } %>)
    <%_ } else { _%>
        <%# 不在同一个模块或在不同的微服务 -%>
        <%_ if (((applicationTypeMonolith || applicationTypeMicroservice) && multiModule && moduleName && moduleName !== relationship.otherEntity.moduleName) ||
                (applicationTypeMicroservice && !(relationship.otherEntity.applications.includes('*') || relationship.otherEntity.applications.includes(baseName)))
        ) { _%>
    @TableField(value = "<%- relationship.columnName %>_<%= this._.snakeCase(relationship.otherEntityField) %>")
        <%_ } else { _%>
    @TableField(exist = false)
    @BindEntity(entity = <%= relationship.otherEntity.persistClass %>.class, condition="this.<%= relationship.columnName %>_id=id")
        <%_ } _%>
    <%_ } _%>
      <%_ if (relationship.relationshipValidate && relationship.relationshipRequired) { _%>
    @NotNull
      <%_ } _%>
  <%_ } else if (relationship.relationshipManyToMany) { -%>
    <%_ if (ormTool === 'hibernate') { _%>
    @ManyToMany(fetch = FetchType.LAZY<% if (!relationship.ownerSide) { %>, mappedBy = "<%= relationship.otherRelationship.propertyName %>"<% } %>)
      <%_ if (relationship.ownerSide) { _%>
        <%_ if (relationship.relationshipValidate && relationship.relationshipRequired) { _%>
    @NotNull
        <%_ } _%>
    @JoinTable(name = "<%= relationship.joinTable.name %>",
               joinColumns = <%= primaryKey.fields.length > 1 ? '{' : '' %>
                   <%_ primaryKey.fields.forEach((field, idx) => { _%>
                   <%= idx === 0 ? '' : ',' %>@JoinColumn(name = "<%= `${entityTableName}_${field.columnName}` %>")
                   <%_ }); _%>
               <%= primaryKey.fields.length > 1 ? '}' : '' %>,
               inverseJoinColumns = <%= relationship.otherEntity.primaryKey.fields.length > 1 ? '{' : '' %>
                   <%_ relationship.otherEntity.primaryKey.fields.forEach((field, idx) => { _%>
                   <%= idx === 0 ? '' : ',' %>@JoinColumn(name = "<%= `${relationship.columnName}_${field.columnName}` %>"))
                   <%_ }); _%>
               <%= relationship.otherEntity.primaryKey.fields.length > 1 ? '}' : '' %>
      <%_ } _%>
    <%_ } else { _%>
    @TableField(exist = false)
    <% if (relationship.ownerSide === true) { _%>
        <%# 不在同一个模块或在不同的微服务 -%>
        <%_ if (((applicationTypeMonolith || applicationTypeMicroservice) && multiModule && moduleName && moduleName !== relationship.otherEntity.moduleName) ||
                (applicationTypeMicroservice && !(relationship.otherEntity.applications.includes('*') || relationship.otherEntity.applications.includes(baseName)))
        ) { _%>
    @BindFieldList(
        entity = <%= asEntity(relationship.otherEntity.primaryKey.fields[0].fieldType) %>.class,<% const otherEntitySortFields = relationship.otherEntity.fields.filter(field => field.options?.sortField); %>
        joinTable = "<%= relationship.joinTable.name %>",
        joinColumn = "<%= entityTableName + '_' + primaryKey.fields[0].columnName %>",
        field="<%= relationship.columnName + '_' + relationship.otherEntity.primaryKey.fields[0].columnName %>",
        condition="this.id=<%= relationship.columnName + '_' + relationship.otherEntity.primaryKey.fields[0].columnName %>"
    )
        <%_ } else { _%>
    @BindEntityList(
        entity = <%= relationship.otherEntity.persistClass %>.class,
        <%_ if (relationship.options?.source?.annotationOnSource?.includes('relateByIdEntity')) { _%>
        condition="this.id=owner_entity_id AND owner_entity_name = '<%= persistClass %>'"
        <% } else { %>
        joinTable = "<%= relationship.joinTable.name %>",
        joinColumn = "<%= entityTableName + '_' + primaryKey.fields[0].columnName %>",
        inverseJoinColumn = "<%= relationship.columnName + '_' + relationship.otherEntity.primaryKey.fields[0].columnName %>",
        condition="this.id=<%= relationship.joinTable.name %>.<%= entityTableName + '_' +  primaryKey.fields[0].columnName %> AND <%= relationship.joinTable.name %>.<%= relationship.columnName + '_' + relationship.otherEntity.primaryKey.fields[0].columnName %>=id"
        <%_ } _%>
        <% const otherEntitySortFields = relationship.otherEntity.fields.filter(field => field.options?.sortField); %>
        <% if (otherEntitySortFields && otherEntitySortFields.length) { %>,
        orderBy = "<%= otherEntitySortFields.map(otherEntitySortField => `${otherEntitySortField.fieldName}:${otherEntitySortField.options?.sortField === 'asc' ? 'ASC' : 'DESC'}`).join(',') %>"
        <% } %>
    )
        <%_ } _%>
    <%_ } else { _%>
    @BindEntityList(
        entity = <%= relationship.otherEntity.persistClass %>.class,
        condition="this.id=<%= relationship.otherRelationship.joinTable.name %>.<%= relationship.otherRelationship.columnName + '_' + primaryKey.fields[0].columnName %> AND <%= relationship.otherRelationship.joinTable.name %>.<%= relationship.otherEntity.entityTableName + '_' + relationship.otherEntity.primaryKey.fields[0].columnName %>=id"
    )
    <%_ } _%>
    <%_ } _%>
  <%_ } else { -%>
      <%_ if (relationship.ownerSide) { -%>
        <%_ if (ormTool === 'hibernate') { _%>
    @OneToOne(fetch = FetchType.LAZY<% if (relationship.relationshipRequired) { %>, optional = false<% } %>)
        <%_ if (relationship.relationshipValidate && relationship.relationshipRequired) { _%>
    @NotNull
        <%_ } _%>
        <%_ if (relationship.id) { %>
    @MapsId
    @JoinColumn(name = "<%= relationship.otherEntity.primaryKey.fields[0].columnName %>")
        <%_ } else { _%>
    @JoinColumn(unique = true)
        <%_ } _%>
        <%_ } else { _%>
    @TableField(exist = false)
    @BindEntity(entity = <%= relationship.otherEntity.persistClass %>.class, <% if (relationship.id) { %>condition="this.<%= primaryKey.name %>=<%= relationship.otherEntity.primaryKey.name %><% } else { %>condition="this.<%= relationship.columnName %>_<%= primaryKey.name %>=<%= relationship.otherEntity.primaryKey.name %><% } %>")
        <%_ } _%>
      <%_ } else { _%>
        <%_ if (ormTool === 'hibernate') { _%>
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "<%= relationship.otherEntityRelationshipName %>")
        <%_ } else { _%>
    @TableField(exist = false)
          <%_ if (relationship.ownerSide) { _%>
    @BindEntity(entity = <%= relationship.otherEntity.persistClass %>.class, <% if (relationship.id) { %>condition="this.<%= primaryKey.name %>=<%= relationship.otherEntity.primaryKey.name %><% } else { %>condition="this.<%= relationship.columnName %>_<%= primaryKey.name %>=<%= relationship.otherEntity.primaryKey.name %><% } %>")
          <%_ } else { _%>
    @BindEntity(entity = <%= relationship.otherEntity.persistClass %>.class, <% if (relationship.id) { %>condition="this.<%= primaryKey.name %>=<%= relationship.otherEntity.primaryKey.name %><% } else { %>condition="this.<%= primaryKey.name %>=<%= relationship.otherRelationship.columnName %>_<%= relationship.otherEntity.primaryKey.name %><% } %>")
          <%_ } -%>
        <%_ } -%>
      <%_ } -%>
  <%_ } -%>
<&_ } -&>
<%_ } -%>
