JAVA Bean 转换工具 BULL 使用简介

How to Transform Any Type of Java Bean With BULL

在跨团队或者跨系统的开发调用时,经常遇到 两个系统Java 代码命名不一致的情况,简单直接的办法就是写一堆get set

如果能拿到对方的jar 或者源码 亦可以使用对方的命名:

例如

对店铺的定义

A系统

public class shop{
	private long id ;
	private String name;
	private String address;
	}

B系统

public class  store{
	private Long  storeId;
	private String name;
	private String location;
	}

BULL 的使用

一、maven 的引入

The project provides two different builds, one compatible with jdk 8 (or above) and one with jdk 11 or above.

BULL提供了两个版本的jar
一个基于JDK8

一个基于JDK11

<dependency>
    <groupId>com.hotels.beans</groupId>
    <artifactId>bull-bean-transformer</artifactId>
    <version>1.7.1</version>
</dependency>

二、特性

The macro features explained in this article are:

JAVA 对象转换 Bean transformation
JAVA 对象验证 Bean validation

三、对象转换

3.1

例如 给出两个不同的bean

public class FromBean {                                     public class ToBean {                           
   private final String name;                                  public BigInteger id;                                  
   private final BigInteger id;                                private final String name;                             
   private final List<FromSubBean> subBeanList;                private final List<String> list;                       
   private List<String> list;                                  private final List<ImmutableToSubFoo> nestedObjectList;
   private final FromSubBean subObject;                        private ImmutableToSubFoo nestedObject;                
    // all args constructor                                     // constructors                                         
   // getters and setters...                                    // getters and setters
}                                                           }

The transformation can be obtained with the following line of code:

ToBean toBean = new BeanUtils().getTransformer().transform(fromBean, ToBean.class);

简单的不同名称,成员变量同名的对象转换,spring 框架也也提供了类似功能。

3.2 不同成员名称的对象转换

Different Field Names Copy

需要组装一个map ,定义好转换的对应关系。

public class FromBean {                                     public class ToBean {                           
   private final String name;                                  private final String differentName;                   
   private final int id;                                       private final int id;                      
   private final List<FromSubBean> subBeanList;                private final List<ToSubBean> subBeanList;                 
   private final List<String> list;                            private final List<String> list;                    
   private final FromSubBean subObject;                        private final ToSubBean subObject;                    
   // all constructors                                         // all args constructor
   // getters...                                               // getters... 
}                                                            }

We need to define proper field mappings and pass it to theTransformer object:

// the first parameter is the field name in the source object
// the second one is the the field name in the destination one 
FieldMapping fieldMapping = new FieldMapping("name", "differentName");
Tansformer transformer = new BeanUtils().getTransformer().withFieldMapping(fieldMapping);

Then, we can perform the transformation:

ToBean toBean = transformer.transform(fromBean, ToBean.class);

3.3 不同层级的数据转换

FromBean 有一个成员也是 Bean 对象

需要FromsubBean 成员 转换成ToBean 成员变量

public class FromSubBean {                         
   private String serialNumber;                 
   private Date creationDate;                    
   // getters and setters... 
}

and our source class and destination class are described as follow:

public class FromBean {                                     public class ToBean {                           
   private final int id;                                       private final int id;                      
   private final String name;                                  private final String name;                   
   private final FromSubBean subObject;                        private final String serialNumber;                 
                                                               private final Date creationDate;                    
   // all args constructor                                     // all args constructor
   // getters...                                               // getters... 
}                                                           }

…and that the values for fields serialNumber and creationDate into the ToBean object need to be retrieved from subObject, this can be done defining the whole path to the property dot separated:

FieldMapping serialNumberMapping = new FieldMapping("subObject.serialNumber", "serialNumber");                                                             
FieldMapping creationDateMapping = new FieldMapping("subObject.creationDate", "creationDate");
ToBean toBean = new BeanUtils().getTransformer()
                   .withFieldMapping(serialNumberMapping, creationDateMapping)
                   .transform(fromBean, ToBean.class);

3.4 使用构造方法

Different Field Names Defining Constructor Args
The mapping between different fields can also be defined by adding @ConstructorArg annotation next to constructor arguments.

The @ConstructorArg takes as input the name of the correspondent field in the source object.

public class FromBean {                                     public class ToBean {                           
   private final String name;                                  private final String differentName;                   
   private final int id;                                       private final int id;                      
   private final List<FromSubBean> subBeanList;                private final List<ToSubBean> subBeanList;                 
   private final List<String> list;                            private final List<String> list;                    
   private final FromSubBean subObject;                        private final ToSubBean subObject;                    
   // all args constructor
   // getters...                                                                }
     
}
subBeanList                                                       

public ToBean(@ConstructorArg("name") final String differentName, 
 @ConstructorArg("id") final int id,
@ConstructorArg("subBeanList") final List<ToSubBean> 
 @ConstructorArg(fieldName ="list") final List<String> list,
 @ConstructorArg("subObject") final ToSubBean subObject) {
 this.differentName = differentName;
this.id = id;
 this.subBeanList = subBeanList;
 this.list = list;
this.subObject = subObject; 
 }
 // getters...           

3.5 使用lamda 表达式转换

Apply a Custom Transformation on a Specific Field Lambda Function

The destination object has a totally different structure than the source object
目标对象和来源对象有不同的结构
We need to perform some operation on a specific field value before copying it
复制操作前需要处理数据
The destination object’s fields have to be validated
目标对象成员变量有校验
The destination object has an additional field than the source object that needs to be filled with something coming from a different source
目标对象有附加的成员变量,来源对象需要做特殊处理

Given the following Source class:

public class FromFoo {
  private final String id;
  private final String val;
  private final List<FromSubFoo> nestedObjectList;
  // all args constructor   
  // getters
}

And the following Destination class:

public class MixedToFoo {
  public String id;
  @NotNull
  private final Double val;
  // constructors
  // getters and setters
}
FieldTransformer<String, Double> valTransformer =
     new FieldTransformer<>("val",
                      n -> Double.valueOf(n) * Math.random());
MixedToFoo mixedToFoo = new BeanUtils().getTransformer()
      .withFieldTransformer(valTransformer)
      .transform(fromFoo, MixedToFoo.class);

3.6 在源对象中缺少字段的情况下应用转换函数

public class FromBean {                                     public class ToBean {                           
   private final String name;                                  @NotNull                   
   private final BigInteger id;                                public BigInteger id;                      
                                                               private final String name;                 
                                                               private String notExistingField; // this will have value: sampleVal
   // all args constructor                                     // constructors...
   // getters...                                               // getters and setters...
}                                                           }

What we need to do is to assign a FieldTransformer function to a specific field:

FieldTransformer<String, String> notExistingFieldTransformer =
                    new FieldTransformer<>("notExistingField", () -> "sampleVal");

以上代码赋予一个固定值,我们可以使用方法
The above functions will assign a fixed value to the field notExistingField, but we can return whatever, for example, we can call an external method that returns a value obtained after a set of operation, something like:
例如:
定义一个calculatevalue()

FieldTransformer<String, String> notExistingFieldTransformer =
                    new FieldTransformer<>("notExistingField", () -> calculateValue());

However, in the end, we just need to pass it to the Transformer.

ToBean toBean = new BeanUtils().getTransformer()
   .withFieldTransformer(notExistingFieldTransformer)
   .transform(fromBean, ToBean.class);

4 Bean Validation

对象验证

The class validation against a set of rules can be precious, especially when we need to be sure that the object data is compliant with our expectations.

The “field validation” aspect is one of the features offered by BULL and it’s totally automatic — you only need to annotate your field with one of the existing javax.validation.constraints (or defining a custom one) and then execute the validation on this.

Given the following bean:

public class SampleBean {                           
   @NotNull                   
   private BigInteger id;                      
   private String name;                 
   // constructor
   // getters and setters... 
}

An instance of the above object:

SampleBean sampleBean = new SampleBean();

And one line of code, such as:

new BeanUtils().getValidator().validate(sampleBean);

This will throw an InvalidBeanException, as the field id isnull.

参考资料:https://dzone.com/articles/how-to-transform-any-type-of-java-bean-with-one-li

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值