目次
まえがき
Setter-Getter メソッドの落とし穴
問題発見
解決策
理由
Mybatis (バージョン 3.4.6) は get-set メソッドを解析して属性名のソース コードを取得します:
Mybatis は get-set メソッドを解析して次のようにします属性名をテストします
@Accessor(chain = true) アノテーションの問題
Reason
ホームページ Java &#&ベース ロンボク島の落とし穴を知る

ロンボク島の落とし穴を知る

Oct 09, 2020 pm 05:00 PM
lombok

java Basic Tutorial コラムでは、簡単に使える Lombok の落とし穴を紹介します。

ロンボク島の落とし穴を知る

まえがき

昨年このプロジェクトに Lombok プラグインが導入されました。これにより、手が本当に解放され、いくつかの反復的な単純なタスク (Getter、 Setter, toString などのメソッド記述) を使用していましたが、使用する過程でいくつかの落とし穴も発見されました。最初は Lombok 問題であることに気づきませんでした。後に、対応する他のコンポーネントのソース コードを追跡し、それはロンボク島の問題であることがわかりました。

Setter-Getter メソッドの落とし穴

問題発見

プロジェクトでは主に Lombok の Setter-Getter メソッドのアノテーションを使用します。これは、結合アノテーション @Data です。 , しかし、プロジェクトでは Mybatis を使用してデータを挿入するプロセス中に問題が発生しました。問題は次のように説明されています:

我们有个实体类:
@Data
public class NMetaVerify{
    private NMetaType nMetaType;
    private Long id;
    ....其他属性
}复制代码
ログイン後にコピー

Mybatis を使用してデータを挿入すると、他の属性は正常に挿入できることがわかりました。しかし、nMetaType 属性はデータベース内にあり、常に null でした。

解決策

Mybatis で SQL の挿入に対応するメソッドを呼び出すプロジェクト コードをデバッグすると、NMetaVerify オブジェクトの nMetaType 属性にはまだデータがあることがわかりますが、挿入を実行した後、データベース nMetaType フィールドは常に null です。最初は列挙型が間違って記述されていると思いました。同様に列挙型を持つ他のフィールドを確認した後、それらはデータベースに正常に挿入できるため、さらに混乱します。 .そこでMybatisのソースコードを辿ってみたところ、Mybatisではリフレクションを利用してnMetaType属性を取得しており、getxxxxメソッドを使用して取得していることが分かりましたが、nMetaTypeのgetメソッドが必要なgetxxxxメソッドとは少し違うようであることが分かりました。 Mybatis著、同じです。問題が見つかりました!

理由

最初の文字が小文字で 2 番目の文字が大文字である属性に対して Lombok によって生成された get-set メソッドは Mybatis によって生成され、idea または get-set メソッドは正式に認められています。 Java の違い:

#Lombok生成的Get-Set方法
@Data
public class NMetaVerify {
    private Long id;
    private NMetaType nMetaType;
    private Date createTime;
    
    public void lombokFound(){
        NMetaVerify nMetaVerify = new NMetaVerify();
        nMetaVerify.setNMetaType(NMetaType.TWO); //注意:nMetaType的set方法为setNMetaType,第一个n字母大写了,
        nMetaVerify.getNMetaType();                                  //getxxxx方法也是大写
    }
}复制代码
ログイン後にコピー
#idea,Mybatis,Java官方默认的行为为:
public class NMetaVerify {
    private Long id;
    private NMetaType nMetaType;
    private Date createTime;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public NMetaType getnMetaType() {//注意:nMetaType属性的第一个字母小写
        return nMetaType;
    }

    public void setnMetaType(NMetaType nMetaType) {//注意:nMetaType属性的第一个字母小写
        this.nMetaType = nMetaType;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}复制代码
ログイン後にコピー

Mybatis (バージョン 3.4.6) は get-set メソッドを解析して属性名のソース コードを取得します:

package org.apache.ibatis.reflection.property;

import java.util.Locale;

import org.apache.ibatis.reflection.ReflectionException;

/**
 * @author Clinton Begin
 */
public final class PropertyNamer {

        private PropertyNamer() {
            // Prevent Instantiation of Static Class
        }

        public static String methodToProperty(String name) {
            if (name.startsWith("is")) {//is开头的一般是bool类型,直接从第二个(索引)开始截取(简单粗暴)
                    name = name.substring(2);
            } else if (name.startsWith("get") || name.startsWith("set")) {//set-get的就从第三个(索引)开始截取
                    name = name.substring(3);
            } else {
                    throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
            }
            //下面这个判断很重要,可以分成两句话开始解释,解释如下
            //第一句话:name.length()==1
            //                      对于属性只有一个字母的,例如private int x;
            //                      对应的get-set方法是getX();setX(int x);
            //第二句话:name.length() > 1 && !Character.isUpperCase(name.charAt(1)))
            //                      属性名字长度大于1,并且第二个(代码中的charAt(1),这个1是数组下标)字母是小写的
            //                      如果第二个char是大写的,那就直接返回name
            if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
                    name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);//让属性名第一个字母小写,然后加上后面的内容
            }

            return name;
        }

        public static boolean isProperty(String name) {
                return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
        }

        public static boolean isGetter(String name) {
                return name.startsWith("get") || name.startsWith("is");
        }

        public static boolean isSetter(String name) {
                return name.startsWith("set");
        }

}复制代码
ログイン後にコピー

Mybatis は get-set メソッドを解析して次のようにします属性名をテストします

    @Test
    public void foundPropertyNamer() {
        String isName = "isName";
        String getName = "getName";
        String getnMetaType = "getnMetaType";
        String getNMetaType = "getNMetaType";

        Stream.of(isName,getName,getnMetaType,getNMetaType)
                .forEach(methodName->System.out.println("方法名字是:"+methodName+" 属性名字:"+ PropertyNamer.methodToProperty(methodName)));
    }
    
    #输出结果如下:
    方法名字是:isName 属性名字:name 
    方法名字是:getName 属性名字:name 
    方法名字是:getnMetaType 属性名字:nMetaType //这个以及下面的属性第二个字母都是大写,所以直接返回name
    方法名字是:getNMetaType 属性名字:NMetaType复制代码
ログイン後にコピー

解決策

1.修改属性名字,让第二个字母小写,或者说是规定所有的属性的前两个字母必须小写
2.如果数据库已经设计好,并且前后端接口对接好了,不想修改,那就专门为这种特殊的属性使用idea生成get-set方法复制代码
ログイン後にコピー

@Accessor(chain = true) アノテーションの問題

問題発見

easyexcel(github.com/)を使用してエクスポートします。 alibaba/eas…) 確認したところ、以前のエンティティクラスのエクスポートは正常でしたが、新しく追加されたエンティティクラスは正常ではありませんでした。比較した結果、新しく追加されたエンティティクラスには @Accessor(chain = true) アノテーション. 私たちの主な目的は、チェーンで set メソッドを呼び出すと便利です:

new UserDto()
.setUserName("")
.setAge(10)
........
.setBirthday(new Date());复制代码
ログイン後にコピー

Reason

easyexcel の最下層は、リフレクション ツールキットとして cglib を使用します:

com.alibaba.excel.read.listener.ModelBuildEventListener 类的第130行
BeanMap.create(resultModel).putAll(map);

最底层的是cglib的BeanMap的这个方法调用

abstract public Object put(Object bean, Object key, Object value);复制代码
ログイン後にコピー

ただし、cglib は Java の rt A メソッドを使用します。jar 内の Introspector クラス:

# Introspector.java 第520行
if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
   pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
   //下面这行判断,只获取返回值是void类型的setxxxx方法
 } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
    // Simple setter
    pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
    if (throwsException(method, PropertyVetoException.class)) {
       pd.setConstrained(true);
    }
}复制代码
ログイン後にコピー

解決策

1.去掉Accessor注解
2.要么就等待easyexcel的作者替换掉底层的cglib或者是其他,反正是支持获取返回值不是void的setxxx方法就行复制代码
ログイン後にコピー

関連する無料学習の推奨事項: Java の基本チュートリアル ##

以上がロンボク島の落とし穴を知るの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

プロによるガイダンス: Eclipse Lombok プラグインを正常にインストールする方法に関する専門家のアドバイスと手順 プロによるガイダンス: Eclipse Lombok プラグインを正常にインストールする方法に関する専門家のアドバイスと手順 Jan 28, 2024 am 09:15 AM

専門的なガイダンス: Lombok プラグインを Eclipse にインストールするための専門家のアドバイスと手順。特定のコード例が必要です。 概要: Lombok は、アノテーションを通じて Java コードの作成を簡素化し、いくつかの強力なツールを提供する Java ライブラリです。この記事では、Eclipse で Lombok プラグインをインストールして構成する方法の手順を読者に紹介し、読者が Lombok プラグインをよりよく理解して使用できるように、いくつかの具体的なコード例を示します。まず Lombok プラグインをダウンロードします。

簡単なチュートリアル: Eclipse に Lombok プラグインをすばやくインストールする 簡単なチュートリアル: Eclipse に Lombok プラグインをすばやくインストールする Jan 28, 2024 am 08:06 AM

クイック スタート: Lombok プラグインを Eclipse にインストールするための簡単なチュートリアル (特定のコード サンプルが必要) Java プロジェクトの開発プロセスでは、Lombok は実用的なプラグインとしてよく使用されます。 Lombok は、Java コードを簡素化し、定型コードの作成を減らし、開発効率を向上させるのに役立ちます。この記事では、Eclipse に Lombok プラグインをインストールして構成する方法を紹介し、具体的なコード例を示します。ステップ 1: Lombok プラグインをダウンロードする まず、Lombok 公式 Web サイトから Lombok プラグインをダウンロードする必要があります。

SpringBoot による Lombok の統合と一般的な問題の解決方法 SpringBoot による Lombok の統合と一般的な問題の解決方法 May 20, 2023 pm 12:46 PM

LombokLombok は Java コードを単純なアノテーションの形で簡略化できるため、開発者の開発効率が向上します。それ自体は優れた Java コード ライブラリです。Lombok は、Java コーディングを簡素化するために便宜的な構文シュガーを使用し、Java コードを合理化する方法を提供します。ただし、Lombok は標準の Java ライブラリではありません。 Web 開発中に Java クラスを記述する必要がある場合、対応するゲッター/セッター、コンストラクター、equals およびその他のメソッドを追加するのに時間がかかります。属性が多い場合、ゲッター/セッター メソッドも多数存在します。これらは非常に長く、技術的な内容があまりありません。属性を変更すると、対応するメソッドの変更を忘れがちです。

Eclipse Lombok プラグインのインストールに関する完全ガイド Eclipse Lombok プラグインのインストールに関する完全ガイド Jan 28, 2024 am 09:58 AM

完全ガイド: Eclipse 用 Lombok プラグインをインストールする方法、特定のコード例が必要 はじめに: Eclipse は、Java 開発用に広く使用されている統合開発環境 (IDE) です。 Lombok は、開発効率を向上させるためにいくつかの退屈なコードを自動化できる Java ライブラリです。この記事では、Eclipse に Lombok プラグインをインストールする方法を詳しく説明し、具体的なコード例を示します。ステップ 1: Lombok プラグインをダウンロードし、Eclipse を開き、「ヘルプ」を選択します。

簡単なインストール: Eclipse に Lombok プラグインをインストールするためのヒント 簡単なインストール: Eclipse に Lombok プラグインをインストールするためのヒント Jan 28, 2024 am 09:29 AM

実践的なヒント: Lombok プラグインを Eclipse に簡単にインストールする方法、具体的なコード例が必要です 日常の Java 開発では、メインの統合開発環境として Eclipse を使用することがよくあります。実際の開発では、Getter メソッドや Setter メソッドを手動で記述するなど、面倒な操作が発生することがあります。これらの操作を簡素化するために、Lombok プラグインを使用すると、これらのコードを自動的に生成できます。 Eclipse に簡単にインストールして設定する方法は次のとおりです。

Javaライブラリlombokとアノテーションの使い方 Javaライブラリlombokとアノテーションの使い方 Jun 03, 2023 pm 09:28 PM

Lombok とは何ですか? Lombok は、コード開発の労力を軽減するために設計された Java ライブラリです。これは、toString メソッド、equals メソッドなど、pojo の最も一般的なセッター/ゲッター メソッドなど、Java の肥大化したテンプレート コードを排除するためのいくつかの簡単なアノテーションを提供します。また、JDK7 がすでに存在する場合でも、ストリームを閉じるのにも役立ちます。 TWR の機能は にありますが、このパッケージはチェックしてみる価値があります。いくつかの簡単な注釈を介して、コンパイル中にテンプレート コードがプログラムに書き込まれます。 Eclipse を使用すると、アウトライン ウィンドウで生成されたメソッドが表示されますが、ソース コードはクリーンです インストールするには、まず lombok 公式 Web サイトにアクセスして、jar パッケージをダウンロードします。 jarパッケージをダウンロードするだけです

Lombok を使用して Java API 開発のコーディングを簡素化する Lombok を使用して Java API 開発のコーディングを簡素化する Jun 18, 2023 pm 11:34 PM

Java は、さまざまな種類のアプリケーションの開発に広く使用されている、一般的に使用されるプログラミング言語です。 Java API は Java 言語の中核部分の 1 つであり、アプリケーションの開発と展開のプロセスを高速化できる、再利用可能な多くのコードとライブラリを開発者に提供します。 Java API の開発プロセスでは、多くの場合、コードの可読性と保守性を向上させるためにコーディングを簡素化するためにいくつかのツールやテクニックを使用する必要があります。 Lombok は Java で使用できる非常に実用的な Java ライブラリです。

Javaのロンボク語にはどのような注釈がありますか? Javaのロンボク語にはどのような注釈がありますか? Apr 30, 2023 pm 03:52 PM

注釈の例 1. @ToString: toString() メソッドを実装します 2. @Data: クラスに注釈が付けられ、クラスのすべてのプロパティの取得および設定メソッドを提供します。さらに、equals、canEqual、hashCode、および toString メソッドが提供されます。 . @Setter: プロパティに関する注釈。プロパティの設定メソッドを提供します。 @Getter: 属性に注釈が付けられ、属性の取得メソッドを提供します @Log4j: クラスに注釈が付けられ、クラスの log という名前の属性を持つ log4j ログ オブジェクトを提供します @NoArgsConstructor: クラスに注釈が付けられ、パラメータのないコンストラクターを提供しますクラス @All

See all articles