Java 实体-实体的映射框架

坚强是说给别人听的谎言 提交于 2020-05-08 05:55:27

<div id="content_views" class="markdown_views"> <!-- flowchart 箭头图标 勿删 --> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> <h3 id="一object-mapping-的技术分类"><a name="t0"></a>一、Object mapping 的技术分类:</h3>

<ul> <li><p>运行期 反射调用set/get 或者是直接对成员变量赋值 。 该方式通过invoke执行赋值 *,实现时一般会采用beanutil, Javassist等开源库。这类的代表:Dozer,ModelMaper</p></li> <li><p>编译期 动态生成set/get代码的class文件 ,在运行时直接调用该class文件。* 该方式实际上扔会存在set/get代码,只是不需要自己写了。 这类的代表:MapStruct,Selma,Orika ### 主要框架性能对比: 每秒钟执行的object mapping越多越好。 <br> <img src="https://img-blog.csdn.net/20180514131105289?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xvdmVyeWNqag==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" alt="这里写图片描述" title=""> <br> 明显可以看出通过在运行期进行反射的方式执行,性能远不如编译器生成class的方式;</p></li> </ul>

<p>MapStruct 与 Selma的对比: <a href="https://java.libhunt.com/project/mapstruct/vs/selma" rel="nofollow" target="_blank">https://java.libhunt.com/project/mapstruct/vs/selma</a> <br> 与 ModelMapper的对比:<a href="https://java.libhunt.com/project/mapstruct/vs/modelmapper" rel="nofollow" target="_blank">https://java.libhunt.com/project/mapstruct/vs/modelmapper</a></p>

<p>综合比较性能、问题排查、文档、成熟度、扩展性等因素来考虑,MapStruct 是一个不错的选择;</p>

<h3 id="二maven依赖与配置"><a name="t1"></a>二、Maven依赖与配置:</h3>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"> &lt;properties&gt; &lt;java.version&gt;<span class="hljs-number">1.8</span>&lt;/java.version&gt; &lt;org.mapstruct.version&gt;<span class="hljs-number">1.2</span><span class="hljs-number">.0</span>.Final&lt;/org.mapstruct.version&gt; &lt;/properties&gt; &lt;dependency&gt; &lt;groupId&gt;org.mapstruct&lt;/groupId&gt; &lt;artifactId&gt;mapstruct-jdk8&lt;/artifactId&gt; &lt;version&gt;${org.mapstruct.version}&lt;/version&gt; &lt;/dependency&gt;<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)">&lt;plugin&gt; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt; &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt; &lt;version&gt;<span class="hljs-number">3.5</span><span class="hljs-number">.1</span>&lt;/version&gt; &lt;configuration&gt; &lt;source&gt;${java.version}&lt;/source&gt; &lt;target&gt;${java.version}&lt;/target&gt; &lt;encoding&gt;${java.encoding}&lt;/encoding&gt; &lt;annotationProcessorPaths&gt; &lt;path&gt; &lt;groupId&gt;org.mapstruct&lt;/groupId&gt; &lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt; &lt;version&gt;${org.mapstruct.version}&lt;/version&gt; &lt;/path&gt; &lt;/annotationProcessorPaths&gt; &lt;/configuration&gt; &lt;/plugin&gt;<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<p>或者可以两个都写成依赖,不需要写成maven插件的形式,后面的依赖用于生成运行期的class实现类,如下:</p>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"> &lt;dependency&gt; &lt;groupId&gt;org.mapstruct&lt;/groupId&gt; &lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt; &lt;version&gt;${org.mapstruct.version}&lt;/version&gt; &lt;scope&gt;provided&lt;/scope&gt; &lt;/dependency&gt;<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<h3 id="三mapstruct的基本使用"><a name="t2"></a>三、MapStruct的基本使用:</h3>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"><span class="hljs-annotation">@Mapper</span>(componentModel = <span class="hljs-string">"spring"</span>) <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">MonitorAppGroupIdcDTOMapper</span> {</span> MonitorAppGroupIdcDTOMapper MAPPER = Mappers.getMapper(MonitorAppGroupIdcDTOMapper.class); <span class="hljs-keyword">void</span> mapping(MonitorAppGroupIdcDTO source, <span class="hljs-annotation">@MappingTarget</span> MonitorAppGroupIdcDTO dest); }<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<p>编译后生成的部分代码结构:</p>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"><span class="hljs-annotation">@Component</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MonitorAppGroupIdcDTOMapperImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MonitorAppGroupIdcDTOMapper</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-title">MonitorAppGroupIdcDTOMapperImpl</span>() { } <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">mapping</span>(MonitorAppGroupIdcDTO source, MonitorAppGroupIdcDTO dest) { <span class="hljs-keyword">if</span>(source != <span class="hljs-keyword">null</span>) { dest.setId(source.getId()); dest.setGmtCreate(source.getGmtCreate()); ... } } }<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<p>可以看出MapStruct还需要依赖对象的get/set方法,有时候编写一堆的get/set方法看上去很不美观,期望能通过自动生成的方式插入get/set方法,其解决方案是使用lombok。mapstrcut官网也有二者结合的例子: <a href="https://github.com/mapstruct/mapstruct/issues/510" rel="nofollow" target="_blank">https://github.com/mapstruct/mapstruct/issues/510</a> Lombok带来的问题是,如果我们期望通过公有的get/set方法范围私有属性时,IDE会提示方法不存在,这个时候我们可以下载安装Intellij Idea中的”Lombok plugin”来解决,但是这种方案带来了一定的繁琐性。比较好的方式是,对于DO或者DTO中的属性,如果属性为私有属性,需要通过get/set方法来访问的,那么就手工生成get/set方法,如果属性本身为共有属性的,那么就可以借助Lombok来自动生成get/set方法了。</p>

<h3 id="四mapstruct的属性与方法"><a name="t3"></a>四、MapStruct的属性与方法:</h3>

<ol> <li>@Mapper注解的componentModel属性 <br> componentModel 属性用于指定自动生成的接口实现类的组件类型。这个属性支持四个值:</li> </ol>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"><span class="hljs-keyword">default</span>: 这是默认的情况,mapstruct不使用任何组件类型, 可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。 cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via <span class="hljs-annotation">@Inject</span> spring: 生成的实现类上面会自动添加一个<span class="hljs-annotation">@Component</span>注解,可以通过Spring的 <span class="hljs-annotation">@Autowired</span>方式进行注入 jsr330: 生成的实现类上会添加<span class="hljs-annotation">@javax</span>.inject.Named 和<span class="hljs-annotation">@Singleton</span>注解,可以通过 <span class="hljs-annotation">@Inject</span>注解获取。<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<h3 id="五下面我们先来看下代码多对象映射如下所示"><a name="t4"></a>五、下面我们先来看下代码,多对象映射如下所示:</h3>

<pre class="prettyprint" name="code"><code class="language-java hljs has-numbering" onclick="mdcp.signin(event)"><span class="hljs-annotation">@Mapper</span>(componentModel = <span class="hljs-string">"spring"</span>) <span class="hljs-comment">//@Mapper</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">GoodInfoMapper</span> {</span> <span class="hljs-comment">//public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);</span> <span class="hljs-annotation">@Mappings</span>({ <span class="hljs-annotation">@Mapping</span>(source = <span class="hljs-string">"type.name"</span>,target = <span class="hljs-string">"typeName"</span>), <span class="hljs-annotation">@Mapping</span>(source = <span class="hljs-string">"good.id"</span>,target = <span class="hljs-string">"goodId"</span>), <span class="hljs-annotation">@Mapping</span>(source = <span class="hljs-string">"good.title"</span>,target = <span class="hljs-string">"goodName"</span>), <span class="hljs-annotation">@Mapping</span>(source = <span class="hljs-string">"good.price"</span>,target = <span class="hljs-string">"goodPrice"</span>) }) <span class="hljs-keyword">public</span> GoodInfoDTO <span class="hljs-title">from</span>(GoodInfoBean good, GoodTypeBean type); }<div class="hljs-button signin" data-title="登录后复制"></div></code></pre>

<p>原文地址 <a href="https://blog.csdn.net/paincupid/article/details/71247255" rel="nofollow" target="_blank">https://blog.csdn.net/paincupid/article/details/71247255</a></p> </div>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!