話題に入る前に、彼はナンセンスのいくつかは、私の以前の記事に話すと言ったが、家庭菜園のブログのアイデアから削除されます。私は、他のホームの記事ビュー、私自身の理由のために光を見に話します。考えられる理由の下に以下の分析:
- 長さが短すぎる:私はスペースは、物品の品質を決定することができないと考え、それを明確に言葉の問題は間違いなく良いことを確認
- あまりにも多くのコードワードは、あまりにも..トークが安い私がコードは話よりも説得力があるが、ほとんどのプログラマは相対的なコードを見てすることを好むと思うのコードを表示しています。私は(相対的に言って、私は良いコードが:)で書き込み言いませんでした)私よりも私のコードが良い書き込みと言うことだと思います
- 品質はありません:私だけは、私はあなたのインスピレーションは、フロントページに公開することを選択した与えるだろうと思います。私は、時間の通って、外に物事を考え、仕事で遭遇本当の問題に関する記事の例としては、実績のあります
自分自身の理由を見つけることがない、私は、彼らの限られたレベル、容量不足を認め、将来の要件を満たすための努力はコメントエリアで私と通信するために歓迎することを願っています。
前回の記事で、私はページネーションクエリの例を使用している、それはコードの重複を排除するために、テンプレートメソッドパターンを使用する方法について説明します。その例は、以下の例を共有するすべての人の理解を深めて少し難しく、比較的簡単です。
まず、シーン記述
私は仕事で遭遇シーンは、メッセージキューは(MQ)システムは、データベーステーブル内のいくつかのフィールドの唯一のお尻は、おそらくプロセスは以下のとおりであるニュースの上に、上流のプッシュを監視していると述べました。
- それは新しいレコードを挿入するために存在しない場合は、データベースの存在を照会する唯一の鍵によると
- 存在する場合、比較対象と上流のプッシュはこれらのフィールドを比較し、オブジェクトデータベースをチェックアウト同じドッキングされています
- あなたが同じであれば、それは何も操作です。異なる場合は、データベースのレコードを更新するために、異なるフィールドでそれを使用
第二に、悪い方法
ドッキングシステムと上流のユーザモジュール、ユーザテーブルにはidが今、一意のキー、ちょうどお尻のID、名前、年齢4つの分野で、ID、名前、年齢、性別四つのフィールドを持っていると仮定します。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private Integer age;
private Integer sex;
}
public class UserDAO {
private User oneUser = new User(1, "u1", 18, 1);
public User getById(Integer id) {
if (id != 1) {
return null;
}
return oneUser;
}
public void updateById(User user) {
Integer id = user.getId();
if (id == null || id != 1) {
return;
}
if (user.getName() != null) {
oneUser.setName(user.getName());
}
if (user.getAge() != null) {
oneUser.setAge(user.getAge());
}
if (user.getSex() != null) {
oneUser.setSex(user.getSex());
}
}
}
/**
* 对比两个对象,获取用于更新的对象
*
* @param toUpdate 要更新的对象
* @param original 原来的对象
* @return 用于更新的对象。如果要比较的字段都一样则返回null
*/
private User getUserUpdate(User toUpdate, User original) {
User updateUser = new User();
if (!original.getName().equals(toUpdate.getName())) {
updateUser.setName(toUpdate.getName());
}
if (!original.getAge().equals(toUpdate.getAge())) {
updateUser.setAge(toUpdate.getAge());
}
if (Stream.of(updateUser.getName(), updateUser.getAge())
.allMatch(Objects::isNull)) {
// 没有更新
return null;
}
return updateUser;
}
MQリスナー方法
// MQ监听方法接收到上游系统推送过来的一条记录,只对接id、name、age字段。id是唯一键(实际中一般不会是id)
User toUpdate = new User(1, "uu1", 20, null);
System.out.println("toUpdate user: " + toUpdate);
// 根据唯一键键去数据库查询查询查询
User original = userDAO.getById(toUpdate.getId());
System.out.println("original user: " + original);
// 如果查到则用上游系统推送的记录去更新这条记录,如果没查到则插入一条新记录
if (original != null) {
// 对比两个对象,获取用于更新的对象
User updateUser = getUserUpdate(toUpdate, original);
// 如果两对象要比较的字段都一样就不操作,否则更新不同的字段
if (updateUser != null) {
// 设置主键id
updateUser.setId(toUpdate.getId());
System.out.println("update user: " + updateUser);
// 根据主键id去更新
userDAO.updateById(updateUser);
System.out.println("updated user: " + userDAO.getById(toUpdate.getId()));
}
} else {
// 插入一条新记录
}
結果:
toUpdate user: User(id=1, name=uu1, age=20, sex=null)
original user: User(id=1, name=u1, age=18, sex=1)
update user: User(id=1, name=uu1, age=20, sex=null)
updated user: User(id=1, name=uu1, age=20, sex=1)
上記のコードの分析のコアgetUserUpdate
方法は、練習ドッキングフィールド多くの場合、メソッドのコードは、エラーが発生しやすいです。設定値が等しい場合、同じフィールドの2つのオブジェクトが等しい比較すること:このアプローチは、反復コードを探します。コードのこの部分が抽出する方法であることができ、次のセクションを参照してください、その後、しばらく考えてください。
第三に、テンプレートメソッド
/**
* 对象更新比较器
*
* @param <T> 待比较的对象类型
*/
public final class UpdateDiffer<T> {
/**
* 原来的对象
*/
private final T original;
/**
* 要更新的对象
*/
private final T toUpdate;
/**
* ”原来的对象“和“要更新的对象”比较出来用于更新的对象
*/
private final T difference;
/**
* 需要比较的字段的get方法
*/
private final List<Function<T, ?>> getMethodList;
/**
* Initializes a newly created UpdateDiffer object
*
* @param original 原来的对象
* @param toUpdate 要更新的对象
* @param tConstructor T类型对象构造方法
*/
public UpdateDiffer(T original, T toUpdate, Supplier<T> tConstructor) {
Objects.requireNonNull(original);
Objects.requireNonNull(toUpdate);
Objects.requireNonNull(tConstructor);
this.original = original;
this.toUpdate = toUpdate;
this.difference = tConstructor.get();
getMethodList = new ArrayList<>();
}
/**
* 比较字段是否相同,如果不同,把要更新的对象字段值设置到difference对象里
*
* @param getMethod get方法
* @param setMethod set方法
* @param <R> get方法的返回值类型/set方法参数类型
* @return this
*/
public <R> UpdateDiffer<T> diffing(Function<T, R> getMethod, BiConsumer<T, R> setMethod) {
Objects.requireNonNull(getMethod);
Objects.requireNonNull(setMethod);
R toUpdateValue = getMethod.apply(toUpdate);
R originalValue = getMethod.apply(original);
Objects.requireNonNull(originalValue, "数据库中的字段不应该为null");
if (!originalValue.equals(toUpdateValue)) {
setMethod.accept(difference, toUpdateValue);
}
// 保存已经调用的get方法
getMethodList.add(getMethod);
return this;
}
/**
* 获取”原来的对象“和“要更新的对象”比较出来的对象,用于去数据库更新(更新前还要再设置id等字段)。
*
* @return ”原来的对象“和“要更新的对象”比较出来用于更新的对象。如果“原来的对象”和“要更新的对象”中所有要比较的字段都相同,返回null
*/
public T diff() {
// 如果difference对象中所有要比较的字段都为null
if (
getMethodList.stream()
.map(getFunction -> getFunction.apply(difference))
.allMatch(Objects::isNull)
) {
return null;
}
return this.difference;
}
}
次のコードで置き換えるgetUserUpdate
方法
User updateUser = new UpdateDiffer<>(original, toUpdate, User::new)
.diffing(User::getName, User::setName)
.diffing(User::getAge, User::setAge)
.diff();
業績と同じの1の結果。
エラーを起こしやすい以前の多くよりもそのクリアコードではなく、ありません。コードを説明するためのものではありません、私はJDKで知らされたComparator
触発を見ることができます理解していない、考え抜かComparator
用法。
IV結論
これまで以上導入するために、みんなの「CTRL」、「C」は、テンプレートモード 「V」 キーは、したがって、数年の寿命を増加します:)
このシリーズのカタログのバック