- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <!-- Generated 2019-1-28 17:18:39 by Glory -->
- <hibernate-mapping>
- <class name="com.glory.pms.sheet.model.AbstractSheetData" abstract="true">
- <id name="objectRrn" column="OBJECT_RRN" type="long">
- <generator class="native" />
- </id>
-
- <version name="lockVersion" column="LOCK_VERSION" type="long"></version>
-
- <property name="orgRrn" column="ORG_RRN" type="long"></property>
- <property name="isActive" column="IS_ACTIVE" type="yes_no"></property>
- <property name="created" column="CREATED"></property>
- <property name="createdBy" column="CREATED_BY" type="string"></property>
- <property name="updated" column="UPDATED"></property>
- <property name="updatedBy" column="UPDATED_BY" type="string"></property>
-
- <property name="style" column="STYLE" type="int"></property>
- <property name="sheetId" column="SHEET_ID" type="string"></property>
- <property name="sheetName" column="SHEET_NAME" type="string"></property>
- <property name="sheetDesc" column="SHEET_DESC" type="string"></property>
- <property name="sheetVersion" column="SHEET_VERSION" type="long"></property>
- <property name="equipmentId" column="EQUIPMENT_ID" type="string"></property>
- <property name="equipmentType" column="EQUIPMENT_TYPE" type="string"></property>
- <property name="partName" column="PART_NAME" type="string"></property>
- <property name="recipe" column="RECIPE" type="string"></property>
- <property name="stepName" column="STEP_NAME" type="string"></property>
-
- <property name="group1" column="GROUP1" type="string"></property>
- <property name="group2" column="GROUP2" type="string"></property>
- <property name="group3" column="GROUP3" type="string"></property>
- <property name="group4" column="GROUP4" type="string"></property>
- <property name="sheetType" column="SHEET_TYPE" type="string"></property>
- <property name="sheetTemplate" column="SHEET_TEMPLATE" type="string"></property>
- <property name="type" column="TYPE" type="string"></property>
- <property name="standardNumber" column="STANDARD_NUMBER" type="string"></property>
- <property name="standardTime" column="STANDARD_TIME" type="string"></property>
- <property name="checkCount" column="CHECK_COUNT" type="long"></property>
- <property name="comments" column="COMMENTS" type="string"></property>
- <property name="judge1" column="JUDGE1" type="string"></property>
- <property name="judge2" column="JUDGE2" type="string"></property>
- <property name="owner" column="OWNER" type="string"></property>
-
- <property name="currentItemSeq" column="CURRENT_ITEM_SEQ" type="java.lang.Long"></property>
-
- <bag name="checkDatas" inverse="false" lazy="true" cascade="all-delete-orphan" table="PMS_SHEET_CHECKT_LINE_DATA">
- <key>
- <column name="SHEET_DATA_RRN" />
- </key>
- <one-to-many class="com.glory.pms.sheet.model.SheetCheckTableLineData" />
- </bag>
- <bag name="dataDatas" inverse="false" lazy="true" cascade="all-delete-orphan" table="PMS_SHEET_DATAS_LINE_DATA">
- <key>
- <column name="SHEET_DATA_RRN" />
- </key>
- <one-to-many class="com.glory.pms.sheet.model.DatasLineData" />
- </bag>
- <bag name="edcSetDatas" inverse="false" lazy="true" cascade="all-delete-orphan" table="PMS_SHEET_EDCSETS_LINE_DATA">
- <key>
- <column name="SHEET_DATA_RRN" />
- </key>
- <one-to-many class="com.glory.pms.sheet.model.EdcSetsLineData" />
- </bag>
- <bag name="partDatas" inverse="false" lazy="true" cascade="all-delete-orphan" table="PMS_SHEET_PARTS_LINE_DATA">
- <key>
- <column name="SHEET_DATA_RRN" />
- </key>
- <one-to-many class="com.glory.pms.sheet.parts.model.PartsLineData" />
- </bag>
- <bag name="imageDatas" inverse="false" lazy="true" cascade="all-delete-orphan" table="PMS_SHEET_DATAS_IMAGE_DATA">
- <key>
- <column name="SHEET_DATA_RRN" />
- </key>
- <one-to-many class="com.glory.pms.sheet.model.ImageData" />
- </bag>
-
- <dynamic-component name="udf">
- </dynamic-component>
- </class>
- </hibernate-mapping>
复制代码 Hibernate框架中用于对象关系映射(ORM)的配置文件,称为hibernate mapping file。这个文件界说了Java类与数据库表之间的映射规则,以及如何将类的属性映射到表的列。下面是对该文件的一些关键点剖析:
- DTD声明:文件开头指定了利用的文档类型界说(DTD),这是为了确保文件遵循Hibernate 3.0映射文件的标准格式。
元素:界说了一个名为com.glory.pms.sheet.model.AbstractSheetData的抽象类。这意味着它不会直接对应于数据库中的一个表,而是作为其他具体类的基类利用。
- id元素:界说了主键属性objectRrn,并指定了利用native生成器策略来生成主键值。native意味着Hibernate会根据底层数据库选择最合适的主键生成策略(比方,对于MySQL可能是auto_increment,对于SQL Server可能是identity等)。
- version元素:界说了乐观锁定版本字段lockVersion,这有助于在并发情况中检测和避免冲突。
- property元素:为类中的每个非集合型属性界说了映射。每个property元素都指定了对应的数据库列名、Java类型以及可选的类型转换器(如type="yes_no"表现布尔值以’Y’/'N’的形式存储在数据库中)。
- bag元素:界说了四个一对多关联的集合属性(checkDatas, dataDatas, edcSetDatas, partDatas, imageDatas)。bag是一个无序的集合,允许重复项,并且这里设置了cascade=“all-delete-orphan”,这意味着对父实体执行的全部操作(生存、更新、删除)都会级联到子实体,并且假如从集合中移除子实体,则会主动删除这些子实体。lazy="true"意味着这些集合默认是懒加载的,只有在实际访问时才会加载数据。
- dynamic-component元素:提供了一种方式来动态地界说组件属性。在这个例子中,udf似乎被预留出来用于用户界说字段,但具体的字段没有在此文件中界说,可能是在代码中通过其他机制添加的。
此映射文件还包含了一些特定的业务逻辑相关的属性,好比装备信息(equipmentId, equipmentType)、工单信息(sheetId, sheetName)、检查信息(checkCount)等,这些反映了应用步伐的具体需求。
二、dynamic-component元素
dynamic-component 元素在 Hibernate 中允许你界说一个可以动态添加或移除属性的组件。这意味着,你可以根据运行时条件来决定哪些字段应该被映射到数据库中,而不需要在编译时固定这些字段。这为应用步伐提供了更大的机动性,特别是在处理那些具有可变布局的数据模子时非常有用。
动态组件的工作原理
- 配置文件中的声明:
- 在你的Hibernate映射文件中,利用 <dynamic-component> 标签来声明一个动态组件。
- 你可以指定这个组件的名字(如udf),它将作为一个属性出如今对应的Java类中。
- 在XML中,你不需要为每个可能的字段界说具体的 <property> 元素;相反,它们将在运行时通过其他机制添加。
- 运行时属性设置:
- 属性可以在运行时通过提供键值对的方式添加到 dynamic-component 对应的实体对象中。
- 这通常涉及到创建一个 Map<String, Object> 来存储这些动态属性,其中键是属性名,值是属性值。
- 当生存实体时,Hibernate会遍历这个 Map 并主动将这些键值对映射到数据库表中的相应列。
- 数据库表设计:
- 数据库表需要能够顺应这种动态性。一种常见的做法是利用EAV(Entity-Attribute-Value)模式,即为每个实体创建三列:实体ID、属性名和属性值。
- 别的,也可以预先界说一组可能的字段,并在需要时仅添补那些实际利用的字段。
- Java类中的表现:
- 在Java类中,dynamic-component 通常表现为一个 Map<String, Object> 或者自界说的类型,该类型可以序列化/反序列化为这样的 Map。
- 比方,假如你有一个名为 udf 的 dynamic-component,那么在Java类中可能会有一个 Map<String, Object> udf; 字段。
- 示例代码:
- public class AbstractSheetData {
- // ... other fields ...
-
- private Map<String, Object> udf = new HashMap<>();
-
- // Getter and setter for the dynamic component
- public Map<String, Object> getUdf() {
- return udf;
- }
- public void setUdf(Map<String, Object> udf) {
- this.udf = udf;
- }
-
- // ... other methods ...
- }
复制代码- AbstractSheetData sheetData = new AbstractSheetData();
- sheetData.getUdf().put("customField1", "value1");
- sheetData.getUdf().put("customField2", 123L);
- // Save or update the entity with these dynamic fields
- session.saveOrUpdate(sheetData);
复制代码
- 查询支持:
- 利用 HQL (Hibernate Query Language) 或 Criteria API 查询包含 dynamic-component 的实体时,可以通过 udf['key'] 的形式访问动态字段。
注意事项
- 性能考虑:由于动态组件引入了额外的复杂性和机动性,它们可能会带来一定的性能开销,尤其是在查询优化方面。确保你的应用确实需要这种级别的机动性。
- 维护难度:随着动态字段数量的增长,维护和理解数据模子可能会变得更加困难。文档化哪些字段是可以动态添加的是很重要的。
- 验证与束缚:对于动态字段,实现验证逻辑和数据库束缚(如非空检查、唯一性等)可能更加复杂,因为它们不是静态界说的。
总之,dynamic-component 提供了一种强盛的方式来处理具有高度可变布局的数据模子,但应当谨慎利用,权衡其带来的机动性与潜在的复杂性和性能本钱。
三、mybatis 如何实现这个功能
MyBatis 是一个流行的持久层框架,它简化了Java应用步伐与数据库之间的交互。不像Hibernate那样提供完整的对象关系映射(ORM)解决方案,MyBatis 更加轻量级,允许开发者编写自界说SQL查询,同时提供了映射效果到Java对象的功能。
要在 MyBatis 中实现类似于 Hibernate dynamic-component 的功能——即动态添加或移除字段的能力——你可以接纳以下几种方法:
1. 利用 Map 来处理动态字段
最简朴的方法是直接利用 Java 的 Map<String, Object> 来表现具有动态属性的对象。你可以在你的 Mapper XML 文件中配置 SQL 查询来顺应这种布局。
示例:
- Java 类:不需要为每个可能的动态字段界说特定的属性,而是用 Map<String, Object> 来生存这些字段。
- public class SheetData {
- private Long objectRrn;
- private Map<String, Object> dynamicFields = new HashMap<>();
-
- // Getters and Setters
- }
复制代码
- Mapper XML:在插入或更新时,可以利用 <foreach> 标签遍历 dynamicFields 并构造动态的 SET 或 INSERT 语句。
- <insert id="insertSheetData" parameterType="SheetData">
- INSERT INTO sheet_data (object_rrn, <include refid="dynamicColumns"/>)
- VALUES (#{objectRrn}, <include refid="dynamicValues"/>)
- </insert>
- <!-- 定义动态列 -->
- <sql id="dynamicColumns">
- <foreach collection="dynamicFields.keySet()" item="key" open="," separator="," close="">
- ${key}
- </foreach>
- </sql>
- <!-- 定义动态值 -->
- <sql id="dynamicValues">
- <foreach collection="dynamicFields.entrySet()" item="entry" open="," separator="," close="">
- #{entry.value}
- </foreach>
- </sql>
复制代码 2. 动态 SQL 构建
MyBatis 支持通过 <if>, <choose>, <when>, <otherwise>, <trim>, <where>, <set>, 和 <foreach> 等标签构建动态 SQL。这使得你可以根据传入参数机动地调整 SQL 语句。
比方,在更新操作中,你可以只包含那些被修改过的字段:
- <update id="updateSheetData" parameterType="SheetData">
- UPDATE sheet_data
- <set>
- <if test="dynamicFields.containsKey('customField1')">
- custom_field_1 = #{dynamicFields.customField1},
- </if>
- <if test="dynamicFields.containsKey('customField2')">
- custom_field_2 = #{dynamicFields.customField2},
- </if>
- <!-- 其他动态字段 -->
- </set>
- WHERE object_rrn = #{objectRrn}
- </update>
复制代码 3. 利用插件扩展 MyBatis
对于更复杂的场景,你可以考虑开发自界说插件或者拦截器来增强 MyBatis 的功能。插件可以用于拦截和修改执行的 SQL 语句、参数映射等。然而,这种方法通常需要更深入的理解和技术能力,并且应该谨慎评估其必要性和维护本钱。
4. 利用注解方式
假如倾向于利用注解而不是 XML 映射文件,MyBatis 也支持通过注解界说 SQL 语句。固然这种方式不如 XML 那样直观地支持复杂的动态 SQL 构建,但可以通过编程逻辑生成 SQL 语句并联合 @SelectProvider, @UpdateProvider 等注解来实现。
总结
MyBatis 提供了多种方式来处理动态字段的问题,从简朴的 Map<String, Object> 联合动态 SQL 到更复杂的插件开发。选择哪种方法取决于项目标具体需求和技术栈的选择。对于大多数情况来说,利用 Map 和内置的动态 SQL 构建工具就充足了。假如你的应用步伐确实需要更高的机动性,那么可以考虑进一步探索 MyBatis 的高级特性。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |