Coder Social home page Coder Social logo

tamper's Introduction

Introduction

tamper是一款处理bean/map进行属性复制映射的工具,支持递归,集合等深度映射.

Why need tamper

这里列觉了几种需要使用tamper的场景:

  • model 和 DO的转化 (DO = Data Object , 数据库对象的设计是一种大宽表的设计,domain/model的设计,会有层次结构&具体)。 比如表设计存储会采用json存储动态数据,而在model中会是具体的属性
  • model 和 VO的转化 (VO = View Object , 公司的产品detail页面,涉及了后端n多个domain/model的组合展示,这时候会进行包装成VO,包装一些页面组装逻辑)
  • model 和 DTO的转化 (DTO = Data Transfer Object ,公司子系统比较多,系统之间会有比较多的rpc等remote调用)
  • form -> bean的转化 (现在流行的几个MVC框架,都已经开始支持view层的参数注入,比如@Paramter(name="field")String , @Form("name=xx")Bean)。 提交的form表单数据,基本都是以map+list为主,就会涉及一个mapping

Why tamper

  • 解决BeanUtils, BeanCopier?使用上的局限,只能针对同名属性的拷贝
  • 相比于BeanUtils,性能提升是它的优势
  • 相比于BeanCopier,类型之间的convertor是它的优势
  • 支持插件方式的扩展,自身框架的设计也是基于插件扩展。

目前的插件支持:

  • default value支持
  • convetor转换
  • script脚本支持 (EL表达式处理)
  • bean creator(嵌套对象自动创建)

Maven repository

<dependency>
   <groupId>com.alibaba.tamper</groupId>
   <artifactId>tamper</artifactId>
   <version>1.0.3</version>
</dependency>

FAQ

1.How to import to eclipse by maven?

  mvn eclipse:eclipse

2.How to build project by maven?

  mvn clean package

3.How to run testcase by maven?

  mvn test

Example1:

自定义映射规则,处理bean/map <-> bean/map

Step 1 (define mapping config)

bean-mappings xmlns="https://github.com/alibaba/tamper/schema/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://github.com/alibaba/tamper/schema/mapping https://raw.github.com/alibaba/tamper/master/src/main/resources/META-INF/mapping.xsd">
        <!--  (bean-bean) mapping 测试 -->
        <bean-mapping batch="true" srcClass="com.agapple.mapping.object.SrcMappingObject" targetClass="com.agapple.mapping.object.TargetMappingObject" reversable="true">
            <field-mapping srcName="intValue" targetName="intValue" />
            <field-mapping targetName="integerValue" script="src.intValue + src.integerValue" /> <!-- 测试script -->
            <field-mapping srcName="start" targetName="start" />
            <field-mapping srcName="name" targetName="targetName" /> <!--  注意不同名 -->
            <field-mapping srcName="mapping" targetName="mapping" mapping="true" />
        </bean-mapping>
    &lt;bean-mapping batch="true" srcClass="com.agapple.mapping.object.NestedSrcMappingObject" targetClass="com.agapple.mapping.object.NestedTargetMappingObject" reversable="true"&gt;
        &lt;field-mapping srcName="name" targetName="name" defaultValue="ljh" /&gt; &lt;!-- 测试default value --&gt;
        &lt;field-mapping srcName="bigDecimalValue" targetName="value" targetClass="string" defaultValue="10" /&gt; &lt;!-- 测试不同名+不同类型+default value  --&gt;
    &lt;/bean-mapping&gt;

&lt;/bean-mappings&gt;</pre>

Step 2 (do mapping)

public BeanMapping srcMapping    = BeanMapping.create(SrcMappingObject.class, TargetMappingObject.class);
public BeanMapping targetMapping = BeanMapping.create(TargetMappingObject.class , SrcMappingObject.class);
@Test
public void testBeanToBean_ok() {
    SrcMappingObject srcRef = new SrcMappingObject();
    srcRef.setIntegerValue(1);
    srcRef.setIntValue(1);
    srcRef.setName("ljh");
    srcRef.setStart(true);

    TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象
    srcMapping.mapping(srcRef, targetRef);

    SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
    targetMapping.mapping(targetRef, newSrcRef);
}</pre>

Example2:

类似于BeanUtils/BeanCopier,根据同名属性进行自动映射,不需要定义任何的mapping.xml

public BeanCopy srcCopy    = BeanCopy.create(SrcMappingObject.class, TargetMappingObject.class);
    public BeanCopy targetCopy = BeanCopy.create(TargetMappingObject.class , SrcMappingObject.class);
@Test
public void testBeanToBean_ok() {
    SrcMappingObject srcRef = new SrcMappingObject();
    srcRef.setIntegerValue(1);
    srcRef.setIntValue(1);
    srcRef.setName("ljh");
    srcRef.setStart(true);

    TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象
    srcCopy.copy(srcRef, targetRef);

    SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
    targetCopy.copy(targetRef, newSrcRef);
}</pre>

Example3:

类似于BeanUtils,处理map<->bean

 public BeanMap beanMap = BeanMap.create(SrcMappingObject.class);

    @Test
    public void testDescribe_Populate_ok() {
        SrcMappingObject srcRef = new SrcMappingObject();
        srcRef.setIntegerValue(1);
        srcRef.setIntValue(1);
        srcRef.setName("ljh");
        srcRef.setStart(true);
    Map map = beanMap.describe(srcRef);

    SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
    beanMap.populate(newSrcRef, map);
}</pre>

Example4:

Mapping API定义映射

BeanMappingBuilder builder = new BeanMappingBuilder() {
        protected void configure() {
            mapping(HashMap.class, HashMap.class).batch(false).reversable(true).keys("src", "target");
            fields(srcField("one"), targetField("oneOther")).convertor("convertor").defaultValue("ljh");
            fields(srcField("two").clazz(String.class), targetField("twoOther")).script("1+2").convertor(
                                                                                                         StringToCommon.class);
            fields(srcField("three").clazz(ArrayList.class), targetField("threeOther").clazz(HashSet.class)).recursiveMapping(
                                                                                                                              true);
        }

    };</pre>

通过builder可以比较方便的构造mapping config,最后需要生成mapping实例,还需要做一步:

BeanMapping mapping = new BeanMapping(builder);
mapping.mapping(src, dest);//使用

or

BeanMappingConfigHelper.getInstance().register(builder); // 进行注册
BeanMappingObject object = BeanMappingConfigHelper.getInstance().getBeanMappingObject(srcClass,targetClass);
mapping.mapping(src, dest);//使用

问题反馈

  1. qq交流群: 161559791
  2. 邮件交流: [email protected]
  3. 新浪微博: agapple0002
  4. 报告issue:issues

tamper's People

Contributors

agapple avatar bryant1410 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tamper's Issues

java.lang.IllegalArgumentException对象copy问题

java.lang.IllegalArgumentException: Cannot find method public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
at net.sf.cglib.reflect.FastMethod.helper(FastMethod.java:39) ~[cglib-3.2.4.jar:na]
at net.sf.cglib.reflect.FastMethod.(FastMethod.java:28) ~[cglib-3.2.4.jar:na]
at net.sf.cglib.reflect.FastClass.getMethod(FastClass.java:104) ~[cglib-3.2.4.jar:na]
at com.agapple.mapping.core.introspect.Introspector.getFastClass(Introspector.java:150) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.introspect.Introspector.getFastMethod(Introspector.java:65) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.introspect.PropertySetExecutor.discover(PropertySetExecutor.java:63) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.introspect.PropertyBatchExecutor.buildGetBulkBean(PropertyBatchExecutor.java:49) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.introspect.PropertyBatchExecutor.(PropertyBatchExecutor.java:19) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.introspect.Uberspector.getBatchExecutor(Uberspector.java:47) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.BeanMappingExecutor.getSetBatchExecutor(BeanMappingExecutor.java:122) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.core.BeanMappingExecutor.execute(BeanMappingExecutor.java:51) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.BeanCopy.copy(BeanCopy.java:59) ~[mapping-1.0.0.jar:na]
at com.agapple.mapping.BeanMappingUtil.copy(BeanMappingUtil.java:33) ~[mapping-1.0.0.jar:na]

建议添加在配置中添加include的配置

建议在配置中添加include功能 引入其他配置的功能,如果项目转换方面的职责全部交给mapping来处理的话,就1个配置文件太笼统了,注册多次配置又显得比较麻烦。

是否支持类似Dozer的map-id的功能

dozer有一个特性,可以根据不同的场景选择不同的映射方式,方法是map的时候提供map-id。
tamper是否支持这个特性,或者有什么变通的办法呢?

另外,文档对配置文件放在哪里,mapper的实例如何获得等等都没有写,对我这种小白实在是有点困惑

请问把属性向上升级怎么做?

public class User{
    private String name;
    private String age;
    private Address address;

    setter ..getter
}

public class Address{
    private Long id;
    private String location;
    private String street;
    private String houseNumber;
    private String otherAttr;

}
public class UserVO{
    private String name;
    private String age;
    private String street;
    private String location;
    private String houseNumber;

}

业务场景:

User 表有 address 属性,类型为Address
前台使用REST接口输出数据,需要把Address中的一个或多个数据向上作为UserVO的属性传递到前台表格展现。

与 springboot 集成时报错

java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method visit.(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V

at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at net.sf.cglib.core.AbstractClassGenerator.<init>(AbstractClassGenerator.java:38)
at net.sf.cglib.reflect.FastClass$Generator.<init>(FastClass.java:55)
at net.sf.cglib.reflect.FastClass.create(FastClass.java:43)
at net.sf.cglib.reflect.FastClass.create(FastClass.java:39)
at com.alibaba.tamper.core.introspect.Introspector.getFastClass(Introspector.java:165)
at com.alibaba.tamper.core.introspect.Introspector.getFastMethod(Introspector.java:66)
at com.alibaba.tamper.core.introspect.FastPropertySetExecutor.discover(FastPropertySetExecutor.java:63)
at com.alibaba.tamper.core.introspect.PropertyBatchExecutor.buildGetBulkBean(PropertyBatchExecutor.java:49)
at com.alibaba.tamper.core.introspect.PropertyBatchExecutor.<init>(PropertyBatchExecutor.java:19)
at com.alibaba.tamper.core.introspect.UberspectImpl.getBatchExecutor(UberspectImpl.java:36)
at com.alibaba.tamper.core.BeanMappingExecutor.getGetBatchExecutor(BeanMappingExecutor.java:180)
at com.alibaba.tamper.core.BeanMappingExecutor.execute(BeanMappingExecutor.java:52)
at com.alibaba.tamper.BeanCopy.copy(BeanCopy.java:55)
at com.zyf.springboot.BeanCopyTest.testCopy_ok(BeanCopyTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:252)
at junit.framework.TestSuite.run(TestSuite.java:247)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

深度拷贝不生效,thrownet.sf.cglib.beans.BulkBeanException: com.alibaba.tamper.object.NestedSrcMappingObject cannot be cast to com.alibaba.tamper.object.NestedTargetMappingObject

将注解去掉后或抛异常,并不能深度拷贝

public void testCopy_ok() {
SrcMappingObject srcRef = new SrcMappingObject();
srcRef.setIntegerValue(1);
srcRef.setIntValue(1);
srcRef.setName("ljh");
srcRef.setStart(true);

    // NestedSrcMappingObject nestedSrcRef = new NestedSrcMappingObject();
    // nestedSrcRef.setBigDecimalValue(BigDecimal.ONE);
    // srcRef.setMapping(nestedSrcRef);

    TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象
    srcCopyer.copy(srcRef, targetRef);
    assertEquals(targetRef.getIntegerValue(), srcRef.getIntegerValue());
    assertEquals(targetRef.getIntValue(), srcRef.getIntValue());
    assertNull(targetRef.getTargetName());// 为null,因为属性不匹配
    assertEquals(targetRef.isStart(), srcRef.isStart());

    SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次
    targetCopyer.copy(targetRef, newSrcRef);
    assertEquals(newSrcRef.getIntegerValue(), targetRef.getIntegerValue());
    assertEquals(newSrcRef.getIntValue(), targetRef.getIntValue());
    assertNull(newSrcRef.getName());// 为null,因为属性不匹配
    assertEquals(newSrcRef.isStart(), targetRef.isStart());
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.