次のクラスがあります:
マッパー
public interface DeviceTokensMapper {
DeviceTokensMapper INSTANCE = Mappers.getMapper(DeviceTokensMapper.class);
@Mappings({
@Mapping(source = "tokenName", target = "tokenName"),
@Mapping(source = "userOsType", target = "osType"),
})
DeviceTokensDTO toDeviceTokensDTO(DeviceTokens deviceTokens);
}
エンティティ:
@Entity
public class DeviceTokens {
@Id
@Column(name="token_name", nullable = false)
private String tokenName;
@Column(name = "os", nullable = false)
@Enumerated
private UserOSType userOsType;
public DeviceTokens() {}
public DeviceTokens(String tokenName, UserOSType userOSType) {
this.tokenName = tokenName;
this.userOsType = userOSType;
}
public String getTokenName() {
return tokenName;
}
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
public UserOSType getUserOsType() {
return userOsType;
}
public void setUserOsType(UserOSType userOsType) {
this.userOsType = userOsType;
}
}
DTO:
public class DeviceTokensDTO {
private String tokenName;
private UserOSType osType;
public DeviceTokensDTO() {}
public DeviceTokensDTO(String tokenName, UserOSType osType) {
this.tokenName = tokenName;
this.osType = osType;
}
public UserOSType getOsType() {
return osType;
}
public void setOsType(UserOSType osType) {
this.osType = osType;
}
public String getTokenName() {
return tokenName;
}
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
}
そして、このマッピングを使用するspring serviceクラスのメソッド:
@Transactional
public DeviceTokensDTO storeToken(String tokenId, UserOSType userOsType) {
DeviceTokens deviceTokens = new DeviceTokens(tokenId, userOsType);
DeviceTokens newDevice = deviceTokensRepository.save(deviceTokens);
return DeviceTokensMapper.INSTANCE.toDeviceTokensDTO(newDevice);
}
上記のメソッドを実行すると、次の例外が表示されます。
エラー[dispatcherServlet] :? -サーブレット[dispatcherServlet]のServlet.service()がパス[]のコンテキストで例外をスローしました[ハンドラー処理が失敗しました。ネストされた例外はJava.lang.ExceptionInInitializerErrorで、根本原因はJava.lang.ClassNotFoundException:dto.DeviceTokensMapperImpl
では、なぜマッパーに実装クラスが必要なのでしょうか。誰かがアドバイスしてくれませんか?ありがとう。
MapStructはコンパイル時にコードを生成し、Mappers.getMapper(DeviceTokensMapper.class);
への呼び出しは、マッパーインターフェイスの生成された実装を探します。何らかの理由で、デプロイメントユニット(WARなど)に欠落しているようです。
ところでSpringをDIコンテナーとして使用する場合、@Mapper(componentModel="spring")
を使用できます。Mappers
ファクトリーを使用する代わりに、依存関係注入を介してマッパーインスタンスを取得できます。
mavenを使用する場合は、次のようにmapstruct-processor依存関係を追加する必要があります。
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>
mapstruct-processor-xxとmapstruct-xxライブラリの両方がプロジェクトに含まれていますか?
同じ問題があり、mapstruct-processor-xxを含めるのを忘れていることに気付きました。
Mavenを使用していますか?はいの場合は、おそらくMavenコンパイラプラグインでのmapstruct-processor設定に失敗しています。
適切な構成は次のとおりです。
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.Apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.6</source> <!-- or higher, depending on your project -->
<target>1.6</target> <!-- or higher, depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Mapstructと一緒にProject lombokを使用している場合は、両方がコンパイル時にソースを生成するため、Mavenコンパイラプラグインで両方を構成する必要があります。
<plugins>
<plugin>
<groupId>org.Apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${Java.version}</source>
<target>${Java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
私のプロジェクトでは、gradleを使用して同じ問題に遭遇しました。そして、build.gradel
から
compile 'org.mapstruct:mapstruct:1.2.0.CR2'
に
compile 'org.mapstruct:mapstruct-jdk8:1.1.0.Final'
compile 'org.mapstruct:mapstruct-processor:1.1.0.Final'
次に、sh&clean&buildをビルドします。それは今動作します!
私の場合、次のようにEclipse(火星)のバグを回避するために<plugin>
タグ内に<pluginManagement>
をラップしました
<pluginManagement>
<plugin> ... </plugin>
</pluginManagement>
<pluginManagement>
タグを削除すると修正されました。
Build.gradleに追加
compile group: 'org.mapstruct',name: 'mapstruct-jdk8',version: 1.2.0.Final
annotationProcessor group: 'org.mapstruct',name: 'mapstruct-processor',version: 1.2.0.Final
設定で注釈処理を有効にする
ボーナス:mapstructのプラグインintellijを追加
マッパークラスまたは関連クラスを作成/編集した後に./gradlew clean build
(Windowsの場合はgradlew.bat
)を実行しなかったため、この問題に遭遇しました。
また、./gradlew clean build -x test
は機能すると思いますが、すべてのテストを実行できるわけではありません。