From 45febda05e98d77d892cc3bea4f414b0ed2ccd37 Mon Sep 17 00:00:00 2001 From: liuzh Date: Mon, 19 Aug 2024 22:34:54 +0800 Subject: [PATCH 1/8] =?UTF-8?q?5.x=E5=88=86=E6=94=AF=EF=BC=8C=E5=9F=BA?= =?UTF-8?q?=E4=BA=8EJdk17=E5=92=8CSpring=20Boot=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- all/mapper/pom.xml | 4 +-- base/pom.xml | 10 +++---- .../java/tk/mybatis/mapper/base/Country.java | 2 +- .../tk/mybatis/mapper/base/genid/Country.java | 2 +- .../tk/mybatis/mapper/base/genid/User.java | 2 +- .../mapper/defaultenumtypehandler/User.java | 2 +- .../generatedvalue/UserAutoIncrement.java | 8 ++--- .../UserAutoIncrementIdentity.java | 2 +- .../mapper/generatedvalue/UserSqlAfter.java | 2 +- .../mapper/helper/FieldHelperTest.java | 2 +- .../tk/mybatis/mapper/helper/FieldTest.java | 4 +-- .../issues/_216_datetime/TimeModel.java | 4 +-- .../issues/_216_datetime/TimeModel2.java | 4 +-- .../issues/_216_datetime/TimeModel3.java | 4 +-- .../mapper/keysql/UserAutoIncrement.java | 6 ++-- .../keysql/UserAutoIncrementIdentity.java | 6 ++-- .../mybatis/mapper/keysql/UserSqlAfter.java | 6 ++-- .../mybatis/mapper/keysql/UserSqlBefore.java | 4 +-- .../mybatis/mapper/model/BaseLogicDelete.java | 8 ++--- .../java/tk/mybatis/mapper/model/Country.java | 4 +-- .../tk/mybatis/mapper/model/Country2.java | 6 ++-- .../tk/mybatis/mapper/model/CountryI.java | 6 ++-- .../tk/mybatis/mapper/model/CountryJDBC.java | 6 ++-- .../tk/mybatis/mapper/model/CountryT.java | 4 +-- .../mybatis/mapper/model/CountryVersion.java | 2 +- .../java/tk/mybatis/mapper/model/Entity.java | 4 +-- .../java/tk/mybatis/mapper/model/TbUser.java | 2 +- .../mapper/model/TbUserLogicDelete.java | 4 +-- .../tk/mybatis/mapper/model/UserInfo.java | 6 ++-- .../tk/mybatis/mapper/model/UserInfoAble.java | 2 +- .../tk/mybatis/mapper/model/UserInfoMap.java | 6 ++-- .../tk/mybatis/mapper/model/UserLogin.java | 6 ++-- .../tk/mybatis/mapper/model/UserLogin2.java | 2 +- .../mybatis/mapper/model/UserLogin2Key.java | 6 ++-- .../tk/mybatis/mapper/model/UserParent.java | 2 +- .../tk/mybatis/mapper/rawresultmap/User.java | 8 ++--- .../tk/mybatis/mapper/typehandler/User.java | 2 +- .../tk/mybatis/mapper/typehandler/User2.java | 6 ++-- .../tk/mybatis/mapper/version/UserInt.java | 4 +-- .../mybatis/mapper/version/UserTimestamp.java | 4 +-- core/pom.xml | 4 +-- .../mapper/annotation/LogicDelete.java | 8 +++-- .../java/tk/mybatis/mapper/code/ORDER.java | 15 ++++++++-- .../java/tk/mybatis/mapper/code/Style.java | 30 +++++++++++++++---- .../tk/mybatis/mapper/entity/EntityTable.java | 2 +- .../mapper/mapperhelper/FieldHelper.java | 2 +- .../resolve/DefaultEntityResolve.java | 2 +- .../mybatis/mapper/annotation/ColumnTest.java | 2 +- .../tk/mybatis/mapper/annotation/IdTest.java | 2 +- .../mybatis/mapper/annotation/TableTest.java | 2 +- .../mapperhelper/ComplexEntityTest.java | 4 +-- .../mapper/mapperhelper/SqlHelperTest.java | 2 +- extra/pom.xml | 5 ---- .../tk/mybatis/mapper/additional/Country.java | 2 +- .../mapper/additional/aggregation/User.java | 4 +-- .../mapper/additional/delete/Course.java | 4 +-- .../dialect/oracle/DemoCountry.java | 2 +- .../mapper/additional/insertlist/User.java | 2 +- .../mapper/additional/select/Book.java | 2 +- .../additional/update/force/CountryInt.java | 2 +- generator/pom.xml | 8 ++--- pom.xml | 28 ++++++++--------- solon-plugin/pom.xml | 4 +-- .../tk/mybatis/solon/test/entity/User.java | 8 ++--- .../tk/mybatis/sample/domain/Country.java | 2 +- .../tk/mybatis/sample/domain/Country.java | 2 +- spring-boot-starter/pom.xml | 10 ++----- spring/pom.xml | 4 +-- .../tk/mybatis/mapper/annotation/Country.java | 2 +- .../mybatis/mapper/configuration/Country.java | 2 +- .../java/tk/mybatis/mapper/xml/Country.java | 2 +- .../mapper/weekend/entity/Country.java | 4 +-- .../mybatis/mapper/weekend/entity/User.java | 2 +- 73 files changed, 185 insertions(+), 165 deletions(-) diff --git a/all/mapper/pom.xml b/all/mapper/pom.xml index c09413976..041e7375e 100644 --- a/all/mapper/pom.xml +++ b/all/mapper/pom.xml @@ -39,8 +39,8 @@ - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api tk.mybatis diff --git a/base/pom.xml b/base/pom.xml index 3b63c4ef0..9fde3310a 100644 --- a/base/pom.xml +++ b/base/pom.xml @@ -40,8 +40,8 @@ - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api @@ -58,9 +58,9 @@ - mysql - mysql-connector-java - 8.0.21 + com.mysql + mysql-connector-j + 8.0.33 test diff --git a/base/src/test/java/tk/mybatis/mapper/base/Country.java b/base/src/test/java/tk/mybatis/mapper/base/Country.java index d8c9a6050..c03435aef 100644 --- a/base/src/test/java/tk/mybatis/mapper/base/Country.java +++ b/base/src/test/java/tk/mybatis/mapper/base/Country.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.base; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/base/genid/Country.java b/base/src/test/java/tk/mybatis/mapper/base/genid/Country.java index 250b41995..59a0cab5e 100644 --- a/base/src/test/java/tk/mybatis/mapper/base/genid/Country.java +++ b/base/src/test/java/tk/mybatis/mapper/base/genid/Country.java @@ -26,7 +26,7 @@ import tk.mybatis.mapper.annotation.KeySql; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/base/genid/User.java b/base/src/test/java/tk/mybatis/mapper/base/genid/User.java index b5121484d..6bd88aef1 100644 --- a/base/src/test/java/tk/mybatis/mapper/base/genid/User.java +++ b/base/src/test/java/tk/mybatis/mapper/base/genid/User.java @@ -2,7 +2,7 @@ import tk.mybatis.mapper.annotation.KeySql; -import javax.persistence.Id; +import jakarta.persistence.Id; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/User.java b/base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/User.java index 2e57b441e..791696171 100644 --- a/base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/User.java +++ b/base/src/test/java/tk/mybatis/mapper/defaultenumtypehandler/User.java @@ -1,6 +1,6 @@ package tk.mybatis.mapper.defaultenumtypehandler; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrement.java b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrement.java index 216e2f0b4..0822c58bf 100644 --- a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrement.java +++ b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrement.java @@ -1,9 +1,9 @@ package tk.mybatis.mapper.generatedvalue; -import javax.persistence.Column; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentity.java b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentity.java index 8a28544f4..9f9aa1264 100644 --- a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentity.java +++ b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserAutoIncrementIdentity.java @@ -1,6 +1,6 @@ package tk.mybatis.mapper.generatedvalue; -import javax.persistence.*; +import jakarta.persistence.*; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfter.java b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfter.java index 979dde4da..caa604cf3 100644 --- a/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfter.java +++ b/base/src/test/java/tk/mybatis/mapper/generatedvalue/UserSqlAfter.java @@ -1,6 +1,6 @@ package tk.mybatis.mapper.generatedvalue; -import javax.persistence.*; +import jakarta.persistence.*; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/helper/FieldHelperTest.java b/base/src/test/java/tk/mybatis/mapper/helper/FieldHelperTest.java index f07a83a67..1e2dc79f4 100644 --- a/base/src/test/java/tk/mybatis/mapper/helper/FieldHelperTest.java +++ b/base/src/test/java/tk/mybatis/mapper/helper/FieldHelperTest.java @@ -29,7 +29,7 @@ import tk.mybatis.mapper.mapperhelper.FieldHelper; import tk.mybatis.mapper.model.Country; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.beans.IntrospectionException; import java.util.List; diff --git a/base/src/test/java/tk/mybatis/mapper/helper/FieldTest.java b/base/src/test/java/tk/mybatis/mapper/helper/FieldTest.java index 19c51d7a0..5e3530bba 100644 --- a/base/src/test/java/tk/mybatis/mapper/helper/FieldTest.java +++ b/base/src/test/java/tk/mybatis/mapper/helper/FieldTest.java @@ -29,8 +29,8 @@ import tk.mybatis.mapper.mapperhelper.FieldHelper; import tk.mybatis.mapper.model.Country; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; diff --git a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel.java b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel.java index fad28a5ed..32bcad037 100644 --- a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel.java +++ b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel.java @@ -1,7 +1,7 @@ package tk.mybatis.mapper.issues._216_datetime; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.io.Serializable; import java.util.Date; diff --git a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2.java b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2.java index a45538f3c..9bafddff8 100644 --- a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2.java +++ b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel2.java @@ -1,7 +1,7 @@ package tk.mybatis.mapper.issues._216_datetime; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; diff --git a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3.java b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3.java index 424aec9f2..5a22b61d7 100644 --- a/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3.java +++ b/base/src/test/java/tk/mybatis/mapper/issues/_216_datetime/TimeModel3.java @@ -3,8 +3,8 @@ import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.io.Serializable; import java.util.Date; diff --git a/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrement.java b/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrement.java index 3293e452b..74425ba60 100644 --- a/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrement.java +++ b/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrement.java @@ -2,9 +2,9 @@ import tk.mybatis.mapper.annotation.KeySql; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentity.java b/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentity.java index 188aa40d3..9bced705a 100644 --- a/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentity.java +++ b/base/src/test/java/tk/mybatis/mapper/keysql/UserAutoIncrementIdentity.java @@ -3,9 +3,9 @@ import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.IdentityDialect; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfter.java b/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfter.java index 707236b7c..a615e5922 100644 --- a/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfter.java +++ b/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlAfter.java @@ -3,9 +3,9 @@ import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.ORDER; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBefore.java b/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBefore.java index d2644d545..fbb536c3a 100644 --- a/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBefore.java +++ b/base/src/test/java/tk/mybatis/mapper/keysql/UserSqlBefore.java @@ -3,8 +3,8 @@ import tk.mybatis.mapper.annotation.KeySql; import tk.mybatis.mapper.code.ORDER; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/model/BaseLogicDelete.java b/base/src/test/java/tk/mybatis/mapper/model/BaseLogicDelete.java index 15f2c5c7f..e9f8cf0e7 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/BaseLogicDelete.java +++ b/base/src/test/java/tk/mybatis/mapper/model/BaseLogicDelete.java @@ -2,10 +2,10 @@ import tk.mybatis.mapper.annotation.LogicDelete; -import javax.persistence.Column; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; public class BaseLogicDelete { diff --git a/base/src/test/java/tk/mybatis/mapper/model/Country.java b/base/src/test/java/tk/mybatis/mapper/model/Country.java index 089f6bc5c..8130118bf 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/Country.java +++ b/base/src/test/java/tk/mybatis/mapper/model/Country.java @@ -27,8 +27,8 @@ import tk.mybatis.mapper.annotation.Order; import tk.mybatis.mapper.entity.IDynamicTableName; -import javax.persistence.Column; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Transient; import java.io.Serializable; import java.util.List; diff --git a/base/src/test/java/tk/mybatis/mapper/model/Country2.java b/base/src/test/java/tk/mybatis/mapper/model/Country2.java index a1e55efa1..54febb952 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/Country2.java +++ b/base/src/test/java/tk/mybatis/mapper/model/Country2.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; /** * Description: Country diff --git a/base/src/test/java/tk/mybatis/mapper/model/CountryI.java b/base/src/test/java/tk/mybatis/mapper/model/CountryI.java index e0e37a46b..0c5b0c59c 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/CountryI.java +++ b/base/src/test/java/tk/mybatis/mapper/model/CountryI.java @@ -27,9 +27,9 @@ import tk.mybatis.mapper.annotation.NameStyle; import tk.mybatis.mapper.code.Style; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; /** * Description: Country diff --git a/base/src/test/java/tk/mybatis/mapper/model/CountryJDBC.java b/base/src/test/java/tk/mybatis/mapper/model/CountryJDBC.java index 27e68fad5..c90065860 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/CountryJDBC.java +++ b/base/src/test/java/tk/mybatis/mapper/model/CountryJDBC.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * Description: Country diff --git a/base/src/test/java/tk/mybatis/mapper/model/CountryT.java b/base/src/test/java/tk/mybatis/mapper/model/CountryT.java index 1c76d7ed6..c4d4b18c9 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/CountryT.java +++ b/base/src/test/java/tk/mybatis/mapper/model/CountryT.java @@ -24,8 +24,8 @@ package tk.mybatis.mapper.model; -import javax.persistence.Id; -import javax.persistence.Transient; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; /** * Description: Country diff --git a/base/src/test/java/tk/mybatis/mapper/model/CountryVersion.java b/base/src/test/java/tk/mybatis/mapper/model/CountryVersion.java index bd32873c6..41ab7da9b 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/CountryVersion.java +++ b/base/src/test/java/tk/mybatis/mapper/model/CountryVersion.java @@ -26,7 +26,7 @@ import tk.mybatis.mapper.annotation.Version; -import javax.persistence.Table; +import jakarta.persistence.Table; /** * Description: Country diff --git a/base/src/test/java/tk/mybatis/mapper/model/Entity.java b/base/src/test/java/tk/mybatis/mapper/model/Entity.java index 5136ee947..20ebde0e2 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/Entity.java +++ b/base/src/test/java/tk/mybatis/mapper/model/Entity.java @@ -26,8 +26,8 @@ import tk.mybatis.mapper.annotation.Order; -import javax.persistence.Id; -import javax.persistence.Transient; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/model/TbUser.java b/base/src/test/java/tk/mybatis/mapper/model/TbUser.java index 6cc6e268c..b5eb2996e 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/TbUser.java +++ b/base/src/test/java/tk/mybatis/mapper/model/TbUser.java @@ -1,6 +1,6 @@ package tk.mybatis.mapper.model; -import javax.persistence.*; +import jakarta.persistence.*; @Table(name = "tb_user") public class TbUser { diff --git a/base/src/test/java/tk/mybatis/mapper/model/TbUserLogicDelete.java b/base/src/test/java/tk/mybatis/mapper/model/TbUserLogicDelete.java index e4a47d1e7..aecc63c6e 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/TbUserLogicDelete.java +++ b/base/src/test/java/tk/mybatis/mapper/model/TbUserLogicDelete.java @@ -1,7 +1,7 @@ package tk.mybatis.mapper.model; -import javax.persistence.Column; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Table; @Table(name = "tb_user") public class TbUserLogicDelete extends BaseLogicDelete { diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserInfo.java b/base/src/test/java/tk/mybatis/mapper/model/UserInfo.java index d391f1ee6..7a317a73e 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserInfo.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserInfo.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserInfoAble.java b/base/src/test/java/tk/mybatis/mapper/model/UserInfoAble.java index 31dba0f3e..a1cdad193 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserInfoAble.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserInfoAble.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.model; -import javax.persistence.*; +import jakarta.persistence.*; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserInfoMap.java b/base/src/test/java/tk/mybatis/mapper/model/UserInfoMap.java index 851329204..e0f3a2ff0 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserInfoMap.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserInfoMap.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import java.io.Serializable; import java.util.HashMap; diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserLogin.java b/base/src/test/java/tk/mybatis/mapper/model/UserLogin.java index bde7eb6f1..9ca5cd2d7 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserLogin.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserLogin.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import java.util.Date; /** diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserLogin2.java b/base/src/test/java/tk/mybatis/mapper/model/UserLogin2.java index 747d3bf2b..fd572dd0f 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserLogin2.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserLogin2.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.model; -import javax.persistence.Table; +import jakarta.persistence.Table; import java.util.Date; /** diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserLogin2Key.java b/base/src/test/java/tk/mybatis/mapper/model/UserLogin2Key.java index 353a77941..ab1541131 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserLogin2Key.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserLogin2Key.java @@ -24,9 +24,9 @@ package tk.mybatis.mapper.model; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; /** * Created by liuzh on 2014/11/21. diff --git a/base/src/test/java/tk/mybatis/mapper/model/UserParent.java b/base/src/test/java/tk/mybatis/mapper/model/UserParent.java index f52317aab..8ec21539d 100644 --- a/base/src/test/java/tk/mybatis/mapper/model/UserParent.java +++ b/base/src/test/java/tk/mybatis/mapper/model/UserParent.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.model; -import javax.persistence.Column; +import jakarta.persistence.Column; /** * @author liuzh_3nofxnp diff --git a/base/src/test/java/tk/mybatis/mapper/rawresultmap/User.java b/base/src/test/java/tk/mybatis/mapper/rawresultmap/User.java index 536fb6aa8..02e537b28 100644 --- a/base/src/test/java/tk/mybatis/mapper/rawresultmap/User.java +++ b/base/src/test/java/tk/mybatis/mapper/rawresultmap/User.java @@ -3,10 +3,10 @@ import tk.mybatis.mapper.annotation.NameStyle; import tk.mybatis.mapper.code.Style; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.Transient; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import java.util.Date; /** diff --git a/base/src/test/java/tk/mybatis/mapper/typehandler/User.java b/base/src/test/java/tk/mybatis/mapper/typehandler/User.java index e42819271..503fad231 100644 --- a/base/src/test/java/tk/mybatis/mapper/typehandler/User.java +++ b/base/src/test/java/tk/mybatis/mapper/typehandler/User.java @@ -2,7 +2,7 @@ import tk.mybatis.mapper.annotation.ColumnType; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/typehandler/User2.java b/base/src/test/java/tk/mybatis/mapper/typehandler/User2.java index fdb6287fd..6d9ca114e 100644 --- a/base/src/test/java/tk/mybatis/mapper/typehandler/User2.java +++ b/base/src/test/java/tk/mybatis/mapper/typehandler/User2.java @@ -1,8 +1,8 @@ package tk.mybatis.mapper.typehandler; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.io.Serializable; /** diff --git a/base/src/test/java/tk/mybatis/mapper/version/UserInt.java b/base/src/test/java/tk/mybatis/mapper/version/UserInt.java index 6ab7261bc..184865512 100644 --- a/base/src/test/java/tk/mybatis/mapper/version/UserInt.java +++ b/base/src/test/java/tk/mybatis/mapper/version/UserInt.java @@ -2,8 +2,8 @@ import tk.mybatis.mapper.annotation.Version; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/base/src/test/java/tk/mybatis/mapper/version/UserTimestamp.java b/base/src/test/java/tk/mybatis/mapper/version/UserTimestamp.java index d4992249b..30542347b 100644 --- a/base/src/test/java/tk/mybatis/mapper/version/UserTimestamp.java +++ b/base/src/test/java/tk/mybatis/mapper/version/UserTimestamp.java @@ -2,8 +2,8 @@ import tk.mybatis.mapper.annotation.Version; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.sql.Timestamp; /** diff --git a/core/pom.xml b/core/pom.xml index 603d18a6a..db365236a 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -40,8 +40,8 @@ - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api diff --git a/core/src/main/java/tk/mybatis/mapper/annotation/LogicDelete.java b/core/src/main/java/tk/mybatis/mapper/annotation/LogicDelete.java index ecd482ecb..f8520fd9e 100644 --- a/core/src/main/java/tk/mybatis/mapper/annotation/LogicDelete.java +++ b/core/src/main/java/tk/mybatis/mapper/annotation/LogicDelete.java @@ -14,12 +14,16 @@ int isDeletedValue() default 1; - // 优先级比isDeletedValue更高 表示以null作为删除记录的标识 + /** + * 优先级比isDeletedValue更高 表示以null作为删除记录的标识 + */ boolean isNullForDeletedValue() default false; int notDeletedValue() default 0; - // 优先级比notDeletedValue更高 表示以null作为未删除记录的标识 + /** + * 优先级比notDeletedValue更高 表示以null作为未删除记录的标识 + */ boolean isNullForNotDeletedValue() default false; } diff --git a/core/src/main/java/tk/mybatis/mapper/code/ORDER.java b/core/src/main/java/tk/mybatis/mapper/code/ORDER.java index a43ba0906..e6d7b1682 100644 --- a/core/src/main/java/tk/mybatis/mapper/code/ORDER.java +++ b/core/src/main/java/tk/mybatis/mapper/code/ORDER.java @@ -6,7 +6,16 @@ * @author liuzh */ public enum ORDER { - AFTER, //insert 后执行 SQL - BEFORE,//insert 前执行 SQL - DEFAULT//使用全局配置 + /** + * insert 后执行 SQL + */ + AFTER, + /** + * insert 前执行 SQL + */ + BEFORE, + /** + * 使用全局配置 + */ + DEFAULT } diff --git a/core/src/main/java/tk/mybatis/mapper/code/Style.java b/core/src/main/java/tk/mybatis/mapper/code/Style.java index 9aa6ad734..f81fff413 100644 --- a/core/src/main/java/tk/mybatis/mapper/code/Style.java +++ b/core/src/main/java/tk/mybatis/mapper/code/Style.java @@ -28,10 +28,28 @@ * 字段转换方式 */ public enum Style { - normal, //原值 - camelhump, //驼峰转下划线 - uppercase, //转换为大写 - lowercase, //转换为小写 - camelhumpAndUppercase, //驼峰转下划线大写形式 - camelhumpAndLowercase, //驼峰转下划线小写形式 + /** + * 原值 + */ + normal, + /** + * 驼峰转下划线 + */ + camelhump, + /** + * 转换为大写 + */ + uppercase, + /** + * 转换为小写 + */ + lowercase, + /** + * 驼峰转下划线大写形式 + */ + camelhumpAndUppercase, + /** + * 驼峰转下划线小写形式 + */ + camelhumpAndLowercase, } diff --git a/core/src/main/java/tk/mybatis/mapper/entity/EntityTable.java b/core/src/main/java/tk/mybatis/mapper/entity/EntityTable.java index 6be558ddf..d5a4c24ff 100644 --- a/core/src/main/java/tk/mybatis/mapper/entity/EntityTable.java +++ b/core/src/main/java/tk/mybatis/mapper/entity/EntityTable.java @@ -33,7 +33,7 @@ import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.util.StringUtil; -import javax.persistence.Table; +import jakarta.persistence.Table; import java.lang.reflect.Constructor; import java.util.*; import java.util.regex.Matcher; diff --git a/core/src/main/java/tk/mybatis/mapper/mapperhelper/FieldHelper.java b/core/src/main/java/tk/mybatis/mapper/mapperhelper/FieldHelper.java index c09051423..7f73e9239 100644 --- a/core/src/main/java/tk/mybatis/mapper/mapperhelper/FieldHelper.java +++ b/core/src/main/java/tk/mybatis/mapper/mapperhelper/FieldHelper.java @@ -27,7 +27,7 @@ import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityField; -import javax.persistence.Entity; +import jakarta.persistence.Entity; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; diff --git a/core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/DefaultEntityResolve.java b/core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/DefaultEntityResolve.java index 7097f6394..fca580b50 100644 --- a/core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/DefaultEntityResolve.java +++ b/core/src/main/java/tk/mybatis/mapper/mapperhelper/resolve/DefaultEntityResolve.java @@ -23,7 +23,7 @@ import tk.mybatis.mapper.util.SqlReservedWords; import tk.mybatis.mapper.util.StringUtil; -import javax.persistence.*; +import jakarta.persistence.*; import java.text.MessageFormat; import java.util.LinkedHashSet; import java.util.List; diff --git a/core/src/test/java/tk/mybatis/mapper/annotation/ColumnTest.java b/core/src/test/java/tk/mybatis/mapper/annotation/ColumnTest.java index e9bcf308e..7e055964e 100644 --- a/core/src/test/java/tk/mybatis/mapper/annotation/ColumnTest.java +++ b/core/src/test/java/tk/mybatis/mapper/annotation/ColumnTest.java @@ -13,7 +13,7 @@ import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; -import javax.persistence.Column; +import jakarta.persistence.Column; import java.util.Set; /** diff --git a/core/src/test/java/tk/mybatis/mapper/annotation/IdTest.java b/core/src/test/java/tk/mybatis/mapper/annotation/IdTest.java index c4cc9473a..89e5e7039 100644 --- a/core/src/test/java/tk/mybatis/mapper/annotation/IdTest.java +++ b/core/src/test/java/tk/mybatis/mapper/annotation/IdTest.java @@ -13,7 +13,7 @@ import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.SqlHelper; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.util.Set; /** diff --git a/core/src/test/java/tk/mybatis/mapper/annotation/TableTest.java b/core/src/test/java/tk/mybatis/mapper/annotation/TableTest.java index 60c090655..1af61e3cf 100644 --- a/core/src/test/java/tk/mybatis/mapper/annotation/TableTest.java +++ b/core/src/test/java/tk/mybatis/mapper/annotation/TableTest.java @@ -8,7 +8,7 @@ import tk.mybatis.mapper.entity.EntityTable; import tk.mybatis.mapper.mapperhelper.EntityHelper; -import javax.persistence.Table; +import jakarta.persistence.Table; /** * @author liuzh diff --git a/core/src/test/java/tk/mybatis/mapper/mapperhelper/ComplexEntityTest.java b/core/src/test/java/tk/mybatis/mapper/mapperhelper/ComplexEntityTest.java index edfba3400..3ae534ed1 100644 --- a/core/src/test/java/tk/mybatis/mapper/mapperhelper/ComplexEntityTest.java +++ b/core/src/test/java/tk/mybatis/mapper/mapperhelper/ComplexEntityTest.java @@ -15,8 +15,8 @@ import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.entity.EntityTable; -import javax.persistence.Column; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Id; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; diff --git a/core/src/test/java/tk/mybatis/mapper/mapperhelper/SqlHelperTest.java b/core/src/test/java/tk/mybatis/mapper/mapperhelper/SqlHelperTest.java index 1589e20de..5795a8755 100644 --- a/core/src/test/java/tk/mybatis/mapper/mapperhelper/SqlHelperTest.java +++ b/core/src/test/java/tk/mybatis/mapper/mapperhelper/SqlHelperTest.java @@ -7,7 +7,7 @@ import tk.mybatis.mapper.code.Style; import tk.mybatis.mapper.entity.Config; -import javax.persistence.*; +import jakarta.persistence.*; public class SqlHelperTest { diff --git a/extra/pom.xml b/extra/pom.xml index f95bf743b..4be2443f9 100644 --- a/extra/pom.xml +++ b/extra/pom.xml @@ -36,11 +36,6 @@ mapper-extra Mybatis 通用 Mapper 扩展方法 - - 8 - 8 - - org.mybatis diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/Country.java b/extra/src/test/java/tk/mybatis/mapper/additional/Country.java index 7cc80c4c6..78b581ff8 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/Country.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/Country.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.additional; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/aggregation/User.java b/extra/src/test/java/tk/mybatis/mapper/additional/aggregation/User.java index 35f0c52ea..be57d8382 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/aggregation/User.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/aggregation/User.java @@ -24,8 +24,8 @@ package tk.mybatis.mapper.additional.aggregation; -import javax.persistence.Id; -import javax.persistence.Transient; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; import java.io.Serializable; /** diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/delete/Course.java b/extra/src/test/java/tk/mybatis/mapper/additional/delete/Course.java index 57c3c237e..278714ef5 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/delete/Course.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/delete/Course.java @@ -2,8 +2,8 @@ import tk.mybatis.mapper.annotation.LogicDelete; -import javax.persistence.Column; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Id; import java.time.LocalDate; /** diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountry.java b/extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountry.java index 93b05399e..8bc13fc34 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountry.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/dialect/oracle/DemoCountry.java @@ -3,7 +3,7 @@ import tk.mybatis.mapper.additional.insertlist.UUIdGenId; import tk.mybatis.mapper.annotation.KeySql; -import javax.persistence.Id; +import jakarta.persistence.Id; /** * @description: diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/insertlist/User.java b/extra/src/test/java/tk/mybatis/mapper/additional/insertlist/User.java index 3f04c739c..84f7ff8d3 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/insertlist/User.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/insertlist/User.java @@ -26,7 +26,7 @@ import tk.mybatis.mapper.annotation.KeySql; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/select/Book.java b/extra/src/test/java/tk/mybatis/mapper/additional/select/Book.java index 05557600e..d883b367e 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/select/Book.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/select/Book.java @@ -1,6 +1,6 @@ package tk.mybatis.mapper.additional.select; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.time.LocalDate; /** diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryInt.java b/extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryInt.java index 45b18293d..7a79554a2 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryInt.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/update/force/CountryInt.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.additional.update.force; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/generator/pom.xml b/generator/pom.xml index 58872fbea..84394ab1c 100644 --- a/generator/pom.xml +++ b/generator/pom.xml @@ -37,8 +37,8 @@ Mybatis 通用 Mapper 代码生成器 - 2.3.28 - 1.4.1 + 2.3.33 + 1.4.2 @@ -73,8 +73,8 @@ test - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api test diff --git a/pom.xml b/pom.xml index 03c61cbf5..9af44aa0e 100644 --- a/pom.xml +++ b/pom.xml @@ -35,20 +35,19 @@ https://mybatis.io - 4.3.0 - 8 - 8 + 5.0.0-SNAPSHOT + 17 + 17 UTF-8 UTF-8 - -Dfile.encoding=UTF-8 - 2.2 - 1.7.26 - 3.5.11 + 3.1.0 + 2.0.16 + 3.5.16 4.13.2 - 2.5.2 - 1.2.11 + 2.7.3 + 1.5.7 @@ -68,24 +67,21 @@ - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api ${jpa.version} - org.mybatis mybatis ${mybatis.version} - provided org.slf4j slf4j-api ${slf4j.version} - provided @@ -111,6 +107,10 @@ + + org.slf4j + slf4j-api + junit diff --git a/solon-plugin/pom.xml b/solon-plugin/pom.xml index 832f263a8..1a0baf882 100644 --- a/solon-plugin/pom.xml +++ b/solon-plugin/pom.xml @@ -72,14 +72,14 @@ com.h2database h2 - 1.4.200 + 2.3.232 test com.zaxxer HikariCP - 4.0.3 + 5.1.0 test diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java index 900149620..bb27cf852 100644 --- a/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java @@ -3,10 +3,10 @@ import org.noear.snack.core.utils.DateUtil; import tk.mybatis.mapper.annotation.LogicDelete; -import javax.persistence.Column; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.util.Date; @Table(name = "`user`") diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/domain/Country.java b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/domain/Country.java index 3e7e12bf9..a1a072bec 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/domain/Country.java +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/java/tk/mybatis/sample/domain/Country.java @@ -27,7 +27,7 @@ import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/domain/Country.java b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/domain/Country.java index 3e7e12bf9..a1a072bec 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/domain/Country.java +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/domain/Country.java @@ -27,7 +27,7 @@ import org.apache.ibatis.type.JdbcType; import tk.mybatis.mapper.annotation.ColumnType; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; /** diff --git a/spring-boot-starter/pom.xml b/spring-boot-starter/pom.xml index b10847a46..a53feb6d5 100644 --- a/spring-boot-starter/pom.xml +++ b/spring-boot-starter/pom.xml @@ -45,9 +45,8 @@ - 3.5.9 - 2.0.7 - 2.6.4 + 3.0.4 + 3.3.2 @@ -102,11 +101,6 @@ mapper-extra ${project.version} - - org.mybatis - mybatis - ${mybatis.version} - org.mybatis mybatis-spring diff --git a/spring/pom.xml b/spring/pom.xml index a5389039f..e3683dbb3 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -37,8 +37,8 @@ Mybatis 通用 Mapper 和 Spring 集成 - 4.3.30.RELEASE - 1.3.3 + 6.1.11 + 3.0.4 diff --git a/spring/src/test/java/tk/mybatis/mapper/annotation/Country.java b/spring/src/test/java/tk/mybatis/mapper/annotation/Country.java index 069b254d0..f8432ba52 100644 --- a/spring/src/test/java/tk/mybatis/mapper/annotation/Country.java +++ b/spring/src/test/java/tk/mybatis/mapper/annotation/Country.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.annotation; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { diff --git a/spring/src/test/java/tk/mybatis/mapper/configuration/Country.java b/spring/src/test/java/tk/mybatis/mapper/configuration/Country.java index 28f2e1221..2d6b6891d 100644 --- a/spring/src/test/java/tk/mybatis/mapper/configuration/Country.java +++ b/spring/src/test/java/tk/mybatis/mapper/configuration/Country.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.configuration; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { diff --git a/spring/src/test/java/tk/mybatis/mapper/xml/Country.java b/spring/src/test/java/tk/mybatis/mapper/xml/Country.java index 0baa38233..260b8180d 100644 --- a/spring/src/test/java/tk/mybatis/mapper/xml/Country.java +++ b/spring/src/test/java/tk/mybatis/mapper/xml/Country.java @@ -24,7 +24,7 @@ package tk.mybatis.mapper.xml; -import javax.persistence.Id; +import jakarta.persistence.Id; import java.io.Serializable; public class Country implements Serializable { diff --git a/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/Country.java b/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/Country.java index 62e7700c8..48dc363c2 100644 --- a/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/Country.java +++ b/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/Country.java @@ -25,8 +25,8 @@ package tk.mybatis.mapper.weekend.entity; -import javax.persistence.Id; -import javax.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.io.Serializable; @Table() diff --git a/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/User.java b/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/User.java index 8766af9d3..9258a5697 100644 --- a/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/User.java +++ b/weekend/src/test/java/tk/mybatis/mapper/weekend/entity/User.java @@ -25,7 +25,7 @@ package tk.mybatis.mapper.weekend.entity; -import javax.persistence.Table; +import jakarta.persistence.Table; /** * @author Frank From 76e46531dd4c548dac574e5b21733db62e2f3368 Mon Sep 17 00:00:00 2001 From: liuzh Date: Mon, 19 Aug 2024 23:25:28 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=EF=BC=8C=E5=A4=84=E7=90=86=E7=BC=96=E8=AF=91=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- all/mapper/pom.xml | 2 +- all/pom.xml | 2 +- core/pom.xml | 4 ++++ generator/pom.xml | 4 ++-- pom.xml | 12 ++++++------ solon-plugin/pom.xml | 2 +- .../mapper-spring-boot-autoconfigure/pom.xml | 4 ++-- 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/all/mapper/pom.xml b/all/mapper/pom.xml index 041e7375e..f597de11f 100644 --- a/all/mapper/pom.xml +++ b/all/mapper/pom.xml @@ -79,7 +79,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.3.0 + 3.6.0 package diff --git a/all/pom.xml b/all/pom.xml index d360522f3..12b924a93 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -87,7 +87,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.1.0 + 1.6.0 true bom diff --git a/core/pom.xml b/core/pom.xml index db365236a..3c98ecf76 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -38,6 +38,10 @@ https://mybatis.io + + org.slf4j + slf4j-api + jakarta.persistence diff --git a/generator/pom.xml b/generator/pom.xml index 84394ab1c..5cbf3ad77 100644 --- a/generator/pom.xml +++ b/generator/pom.xml @@ -57,13 +57,13 @@ org.projectlombok lombok - 1.16.22 + 1.18.34 provided io.swagger swagger-annotations - 1.5.20 + 1.6.14 provided diff --git a/pom.xml b/pom.xml index 9af44aa0e..b6ea3b8f6 100644 --- a/pom.xml +++ b/pom.xml @@ -157,7 +157,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.13.0 -parameters @@ -167,7 +167,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.1.0 + 1.6.0 true resolveCiFriendliesOnly @@ -201,7 +201,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 package @@ -215,7 +215,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.8.0 -Xdoclint:none @@ -234,7 +234,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.5 sign-artifacts @@ -254,7 +254,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.12 + 1.7.0 true ossrh diff --git a/solon-plugin/pom.xml b/solon-plugin/pom.xml index 1a0baf882..a1c96260f 100644 --- a/solon-plugin/pom.xml +++ b/solon-plugin/pom.xml @@ -72,7 +72,7 @@ com.h2database h2 - 2.3.232 + 1.4.200 test diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml b/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml index e3d165441..7b9be7921 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml @@ -74,8 +74,8 @@ true - javax.annotation - javax.annotation-api + jakarta.persistence + jakarta.persistence-api true From 5e7851d824c3c2c6d3bb7706081076bda15a93f3 Mon Sep 17 00:00:00 2001 From: liuzh Date: Mon, 19 Aug 2024 23:45:23 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E9=80=82=E9=85=8DSpring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MapperAutoConfiguration.java | 2 +- .../main/resources/META-INF/spring.factories | 3 - ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/application.properties | 2 +- .../mybatis/sample/SampleXmlApplication.java | 2 +- .../src/main/resources/application.yml | 5 +- .../mybatis/spring/annotation/MapperScan.java | 149 ++-- .../annotation/MapperScannerRegistrar.java | 250 +++++-- .../spring/annotation/MapperScans.java | 41 ++ .../spring/mapper/ClassPathMapperScanner.java | 334 ++++++--- .../mapper/MapperScannerConfigurer.java | 655 ++++++++++++------ .../spring/mapper/SpringBootBindUtil.java | 108 +-- .../annotation/SpringAnnotationTest.java | 3 +- 13 files changed, 1016 insertions(+), 539 deletions(-) delete mode 100644 spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories create mode 100644 spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java index ad420d889..344bbdd5d 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java @@ -202,7 +202,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B logger.debug("Searching for mappers annotated with @Mapper"); - ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); + ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry, environment); scanner.setMapperProperties(environment); try { if (this.resourceLoader != null) { diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 39e242f48..000000000 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -tk.mybatis.mapper.autoconfigure.MapperAutoConfiguration diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..48243cbf6 --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +tk.mybatis.mapper.autoconfigure.MapperAutoConfiguration \ No newline at end of file diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties index a077c532c..dca3cf5cf 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties @@ -21,6 +21,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # -spring.datasource.schema=import.sql +spring.sql.init.schema-locations=classpath:import.sql logging.level.root=WARN logging.level.tk.mybatis.sample.mapper=TRACE \ No newline at end of file diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java index 8473e4443..57fdf5de2 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java @@ -48,7 +48,7 @@ public static void main(String[] args) { public void run(String... args) throws Exception { Country c = countryMapper.selectByPrimaryKey(1); System.out.println("Key : 1, Country Name: " + c.getCountryname()); - c.setId(null); + c.setId(1000L); c.setCountryname("新名字"); countryMapper.insert(c); System.out.println("New Key: " + c.getId()); diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml index 997c1e7b7..31048949b 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml @@ -22,8 +22,9 @@ # THE SOFTWARE. # spring: - datasource: - schema: import.sql + sql: + init: + schema-locations: classpath:import.sql mybatis: config-location: mybatis-config.xml base-packages: tk.mybatis.sample.mapper diff --git a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScan.java b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScan.java index 0dab98301..f26f24b17 100644 --- a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScan.java +++ b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScan.java @@ -1,34 +1,41 @@ -/** - * Copyright 2010-2016 the original author or authors. - *

+/* + * Copyright 2010-2023 the original author or authors. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * https://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - package tk.mybatis.spring.annotation; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.AliasFor; import tk.mybatis.spring.mapper.MapperFactoryBean; import tk.mybatis.spring.mapper.MapperScannerConfigurer; import java.lang.annotation.*; /** - * Use this annotation to register MyBatis mapper interfaces when using Java - * Config. It performs when same work as {@link MapperScannerConfigurer} via - * {@link tk.mybatis.spring.annotation.MapperScannerRegistrar}. + * Use this annotation to register MyBatis mapper interfaces when using Java Config. It performs when same work as + * {@link MapperScannerConfigurer} via {@link MapperScannerRegistrar}. + *

+ * Either {@link #basePackageClasses} or {@link #basePackages} (or its alias {@link #value}) may be specified to define + * specific packages to scan. Since 2.0.4, If specific packages are not defined, scanning will occur from the package of + * the class that declares this annotation. + *

+ * Configuration example: + *

* - *

Configuration example:

*
  * @Configuration
  * @MapperScan("org.mybatis.spring.sample.mapper")
@@ -36,9 +43,7 @@
  *
  *   @Bean
  *   public DataSource dataSource() {
- *     return new EmbeddedDatabaseBuilder()
- *              .addScript("schema.sql")
- *              .build();
+ *     return new EmbeddedDatabaseBuilder().addScript("schema.sql").build();
  *   }
  *
  *   @Bean
@@ -57,86 +62,139 @@
  *
  * @author Michael Lanyon
  * @author Eduardo Macarron
- *
- * @since 1.2.0
- * @see tk.mybatis.spring.annotation.MapperScannerRegistrar
+ * @author Qimiao Chen
+ * @see MapperScannerRegistrar
  * @see MapperFactoryBean
+ * @since 1.2.0
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 @Documented
-@Import(tk.mybatis.spring.annotation.MapperScannerRegistrar.class)
+@Import(MapperScannerRegistrar.class)
+@Repeatable(MapperScans.class)
 public @interface MapperScan {
 
     /**
-     * Alias for the {@link #basePackages()} attribute. Allows for more concise
-     * annotation declarations e.g.:
-     * {@code @EnableMyBatisMapperScanner("org.my.pkg")} instead of {@code
-     * @EnableMyBatisMapperScanner(basePackages= "org.my.pkg"})}.
+     * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
+     * {@code @MapperScan("org.my.pkg")} instead of {@code @MapperScan(basePackages = "org.my.pkg"})}.
+     *
+     * @return base package names
      */
+    @AliasFor("basePackages")
     String[] value() default {};
 
     /**
-     * Base packages to scan for MyBatis interfaces. Note that only interfaces
-     * with at least one method will be registered; concrete classes will be
-     * ignored.
+     * Base packages to scan for MyBatis interfaces. Note that only interfaces with at least one method will be
+     * registered; concrete classes will be ignored.
+     *
+     * @return base package names for scanning mapper interface
      */
+    @AliasFor("value")
     String[] basePackages() default {};
 
     /**
-     * Type-safe alternative to {@link #basePackages()} for specifying the packages
-     * to scan for annotated components. The package of each class specified will be scanned.
-     * 

Consider creating a special no-op marker class or interface in each package - * that serves no purpose other than being referenced by this attribute. + * Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The + * package of each class specified will be scanned. + *

+ * Consider creating a special no-op marker class or interface in each package that serves no purpose other than being + * referenced by this attribute. + * + * @return classes that indicate base package for scanning mapper interface */ Class[] basePackageClasses() default {}; /** - * The {@link BeanNameGenerator} class to be used for naming detected components - * within the Spring container. + * The {@link BeanNameGenerator} class to be used for naming detected components within the Spring container. + * + * @return the class of {@link BeanNameGenerator} */ Class nameGenerator() default BeanNameGenerator.class; /** * This property specifies the annotation that the scanner will search for. *

- * The scanner will register all interfaces in the base package that also have - * the specified annotation. + * The scanner will register all interfaces in the base package that also have the specified annotation. *

* Note this can be combined with markerInterface. + * + * @return the annotation that the scanner will search for */ Class annotationClass() default Annotation.class; /** * This property specifies the parent that the scanner will search for. *

- * The scanner will register all interfaces in the base package that also have - * the specified interface class as a parent. + * The scanner will register all interfaces in the base package that also have the specified interface class as a + * parent. *

* Note this can be combined with annotationClass. + * + * @return the parent that the scanner will search for */ Class markerInterface() default Class.class; /** - * Specifies which {@code SqlSessionTemplate} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. + * + * @return the bean name of {@code SqlSessionTemplate} */ String sqlSessionTemplateRef() default ""; /** - * Specifies which {@code SqlSessionFactory} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. + * + * @return the bean name of {@code SqlSessionFactory} */ String sqlSessionFactoryRef() default ""; /** * Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean. * + * @return the class of {@code MapperFactoryBean} */ Class factoryBean() default MapperFactoryBean.class; + /** + * Whether enable lazy initialization of mapper bean. + *

+ * Default is {@code false}. + *

+ * + * @return set {@code true} to enable lazy initialization + * @since 2.0.2 + */ + String lazyInitialization() default ""; + + /** + * Specifies the default scope of scanned mappers. + *

+ * Default is {@code ""} (equiv to singleton). + *

+ * + * @return the default scope + */ + String defaultScope() default AbstractBeanDefinition.SCOPE_DEFAULT; + + /** + * Specifies a flag that whether execute a property placeholder processing or not. + *

+ * The default is {@literal true}. This means that a property placeholder processing execute. + * + * @return a flag that whether execute a property placeholder processing or not + * @since 3.0.3 + */ + boolean processPropertyPlaceHolders() default true; + + /** + * Specifies which types are not eligible for mapper scanning. + * + * @return array of customized mapper excludeFilter + * @since 3.0.3 + */ + ComponentScan.Filter[] excludeFilters() default {}; + /** * 通用 Mapper 的配置,一行一个配置 * @@ -150,11 +208,4 @@ * @return */ String mapperHelperRef() default ""; - - /** - * Whether enable lazy initialization of mapper bean. - * Default is {@code false}. - * @return set {@code true} to enable lazy initialization - */ - String lazyInitialization() default ""; -} \ No newline at end of file +} diff --git a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScannerRegistrar.java b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScannerRegistrar.java index a06bb6a55..6f6101a22 100644 --- a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -1,106 +1,165 @@ -/** - * Copyright 2010-2016 the original author or authors. - *

+/* + * Copyright 2010-2024 the original author or authors. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * https://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - package tk.mybatis.spring.annotation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import tk.mybatis.spring.mapper.ClassPathMapperScanner; import tk.mybatis.spring.mapper.MapperFactoryBean; +import tk.mybatis.spring.mapper.MapperScannerConfigurer; import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; +/** + * A {@link ImportBeanDefinitionRegistrar} to allow annotation configuration of MyBatis mapper scanning. Using + * an @Enable annotation allows beans to be registered via @Component configuration, whereas implementing + * {@code BeanDefinitionRegistryPostProcessor} will work for XML configuration. + * + * @author Michael Lanyon + * @author Eduardo Macarron + * @author Putthiphong Boonphong + * + * @see MapperFactoryBean + * @see ClassPathMapperScanner + * + * @since 1.2.0 + */ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { - public static final Logger LOGGER = LoggerFactory.getLogger(MapperScannerRegistrar.class); - private ResourceLoader resourceLoader; + public static final Logger LOGGER = LoggerFactory.getLogger(MapperScannerRegistrar.class); + + // Note: Do not move resourceLoader via cleanup + private ResourceLoader resourceLoader; private Environment environment; @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } - AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); - ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); - // this check is needed in Spring 3.1 - if (resourceLoader != null) { - scanner.setResourceLoader(resourceLoader); + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + var mapperScanAttrs = AnnotationAttributes + .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); + if (mapperScanAttrs != null) { + registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry, + generateBaseBeanName(importingClassMetadata, 0)); } + } + + void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, + BeanDefinitionRegistry registry, String beanName) { + + var builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); + builder.addPropertyValue("processPropertyPlaceHolders", annoAttrs.getBoolean("processPropertyPlaceHolders")); Class annotationClass = annoAttrs.getClass("annotationClass"); if (!Annotation.class.equals(annotationClass)) { - scanner.setAnnotationClass(annotationClass); + builder.addPropertyValue("annotationClass", annotationClass); } Class markerInterface = annoAttrs.getClass("markerInterface"); if (!Class.class.equals(markerInterface)) { - scanner.setMarkerInterface(markerInterface); + builder.addPropertyValue("markerInterface", markerInterface); } Class generatorClass = annoAttrs.getClass("nameGenerator"); if (!BeanNameGenerator.class.equals(generatorClass)) { - scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass)); + builder.addPropertyValue("nameGenerator", BeanUtils.instantiateClass(generatorClass)); } Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { - scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass)); + builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); } - scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef")); - scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef")); + var sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef"); + if (StringUtils.hasText(sqlSessionTemplateRef)) { + builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef")); + } - List basePackages = new ArrayList(); - for (String pkg : annoAttrs.getStringArray("value")) { - if (StringUtils.hasText(pkg)) { - basePackages.add(pkg); - } + var sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef"); + if (StringUtils.hasText(sqlSessionFactoryRef)) { + builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef")); } - for (String pkg : annoAttrs.getStringArray("basePackages")) { - if (StringUtils.hasText(pkg)) { - basePackages.add(pkg); - } + + List basePackages = new ArrayList<>(Arrays.stream(annoAttrs.getStringArray("basePackages")) + .filter(StringUtils::hasText).collect(Collectors.toList())); + + basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName) + .collect(Collectors.toList())); + + if (basePackages.isEmpty()) { + basePackages.add(getDefaultBasePackage(annoMeta)); } - for (Class clazz : annoAttrs.getClassArray("basePackageClasses")) { - basePackages.add(ClassUtils.getPackageName(clazz)); + + var excludeFilterArray = annoAttrs.getAnnotationArray("excludeFilters"); + if (excludeFilterArray.length > 0) { + List typeFilters = new ArrayList<>(); + List> rawTypeFilters = new ArrayList<>(); + for (AnnotationAttributes excludeFilters : excludeFilterArray) { + if (excludeFilters.getStringArray("pattern").length > 0) { + // in oder to apply placeholder resolver + rawTypeFilters.addAll(parseFiltersHasPatterns(excludeFilters)); + } else { + typeFilters.addAll(typeFiltersFor(excludeFilters)); + } + } + builder.addPropertyValue("excludeFilters", typeFilters); + builder.addPropertyValue("rawExcludeFilters", rawTypeFilters); } + //优先级 mapperHelperRef > properties > springboot String mapperHelperRef = annoAttrs.getString("mapperHelperRef"); String[] properties = annoAttrs.getStringArray("properties"); if (StringUtils.hasText(mapperHelperRef)) { - scanner.setMapperHelperBeanName(mapperHelperRef); + builder.addPropertyValue("mapperHelperBeanName", mapperHelperRef); } else if (properties != null && properties.length > 0) { - scanner.setMapperProperties(properties); + builder.addPropertyValue("mapperProperties", properties); } else { try { - scanner.setMapperProperties(this.environment); + builder.addPropertyValue("mapperProperties", this.environment); } catch (Exception e) { LOGGER.warn("只有 Spring Boot 环境中可以通过 Environment(配置文件,环境变量,运行参数等方式) 配置通用 Mapper," + "其他环境请通过 @MapperScan 注解中的 mapperHelperRef 或 properties 参数进行配置!" + @@ -108,22 +167,119 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B } } - String lazyInitialization = annoAttrs.getString("lazyInitialization"); + var lazyInitialization = annoAttrs.getString("lazyInitialization"); if (StringUtils.hasText(lazyInitialization)) { - scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); + builder.addPropertyValue("lazyInitialization", lazyInitialization); } - scanner.registerFilters(); - scanner.doScan(StringUtils.toStringArray(basePackages)); + var defaultScope = annoAttrs.getString("defaultScope"); + if (!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)) { + builder.addPropertyValue("defaultScope", defaultScope); + } + + builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); + + // for spring-native + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + + registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); + } - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; + /** + * Parse excludeFilters which FilterType is REGEX or ASPECTJ + * + * @param filterAttributes + * AnnotationAttributes of excludeFilters + * + * @since 3.0.3 + */ + private List> parseFiltersHasPatterns(AnnotationAttributes filterAttributes) { + + List> rawTypeFilters = new ArrayList<>(); + FilterType filterType = filterAttributes.getEnum("type"); + var expressionArray = filterAttributes.getStringArray("pattern"); + for (String expression : expressionArray) { + switch (filterType) { + case REGEX: + case ASPECTJ: + Map typeFilter = new HashMap<>(16); + typeFilter.put("type", filterType.name().toLowerCase()); + typeFilter.put("expression", expression); + rawTypeFilters.add(typeFilter); + break; + default: + throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + + " FilterType in exclude filter of @MapperScan"); + } + } + return rawTypeFilters; } - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; + /** + * Parse excludeFilters which FilterType is ANNOTATION ASSIGNABLE or CUSTOM + * + * @param filterAttributes + * AnnotationAttributes of excludeFilters + * + * @since 3.0.3 + */ + private List typeFiltersFor(AnnotationAttributes filterAttributes) { + + List typeFilters = new ArrayList<>(); + FilterType filterType = filterAttributes.getEnum("type"); + + for (Class filterClass : filterAttributes.getClassArray("value")) { + switch (filterType) { + case ANNOTATION: + Assert.isAssignable(Annotation.class, filterClass, + "Specified an unsupported type in 'ANNOTATION' exclude filter of @MapperScan"); + @SuppressWarnings("unchecked") + var annoClass = (Class) filterClass; + typeFilters.add(new AnnotationTypeFilter(annoClass)); + break; + case ASSIGNABLE_TYPE: + typeFilters.add(new AssignableTypeFilter(filterClass)); + break; + case CUSTOM: + Assert.isAssignable(TypeFilter.class, filterClass, + "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); + typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); + break; + default: + throw new IllegalArgumentException("Cannot specify the 'value' or 'classes' attribute if use the " + + filterType + " FilterType in exclude filter of @MapperScan"); + } + } + return typeFilters; } + + private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { + return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index; + } + + private static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) { + return ClassUtils.getPackageName(importingClassMetadata.getClassName()); + } + + /** + * A {@link MapperScannerRegistrar} for {@link MapperScans}. + * + * @since 2.0.0 + */ + static class RepeatingRegistrar extends MapperScannerRegistrar { + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + var mapperScansAttrs = AnnotationAttributes + .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName())); + if (mapperScansAttrs != null) { + var annotations = mapperScansAttrs.getAnnotationArray("value"); + for (var i = 0; i < annotations.length; i++) { + registerBeanDefinitions(importingClassMetadata, annotations[i], registry, + generateBaseBeanName(importingClassMetadata, i)); + } + } + } + } + } diff --git a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java new file mode 100644 index 000000000..b4b3bac80 --- /dev/null +++ b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tk.mybatis.spring.annotation; + +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * The Container annotation that aggregates several {@link org.mybatis.spring.annotation.MapperScan} annotations. + *

+ * Can be used natively, declaring several nested {@link org.mybatis.spring.annotation.MapperScan} annotations. Can also be used in conjunction with + * Java 8's support for repeatable annotations, where {@link org.mybatis.spring.annotation.MapperScan} can simply be declared several times on the + * same method, implicitly generating this container annotation. + * + * @author Kazuki Shimizu + * + * @since 2.0.0 + * + * @see org.mybatis.spring.annotation.MapperScan + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@Import(MapperScannerRegistrar.RepeatingRegistrar.class) +public @interface MapperScans { + MapperScan[] value(); +} diff --git a/spring/src/main/java/tk/mybatis/spring/mapper/ClassPathMapperScanner.java b/spring/src/main/java/tk/mybatis/spring/mapper/ClassPathMapperScanner.java index 11279ddb8..ff9e127d6 100644 --- a/spring/src/main/java/tk/mybatis/spring/mapper/ClassPathMapperScanner.java +++ b/spring/src/main/java/tk/mybatis/spring/mapper/ClassPathMapperScanner.java @@ -1,12 +1,12 @@ -/** - * Copyright 2010-2016 the original author or authors. - *

+/* + * Copyright 2010-2024 the original author or authors. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * https://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,20 +15,25 @@ */ package tk.mybatis.spring.mapper; +import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; -import org.mybatis.spring.mapper.MapperScannerConfigurer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.scope.ScopedProxyFactoryBean; +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.aot.AotDetector; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; +import org.springframework.core.NativeDetector; import org.springframework.core.env.Environment; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; @@ -37,33 +42,37 @@ import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; -import java.io.IOException; import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Properties; -import java.util.Set; +import java.util.*; /** - * A {@link ClassPathBeanDefinitionScanner} that registers Mappers by - * {@code basePackage}, {@code annotationClass}, or {@code markerInterface}. If - * an {@code annotationClass} and/or {@code markerInterface} is specified, only - * the specified types will be searched (searching for all interfaces will be - * disabled). + * A {@link ClassPathBeanDefinitionScanner} that registers Mappers by {@code basePackage}, {@code annotationClass}, or + * {@code markerInterface}. If an {@code annotationClass} and/or {@code markerInterface} is specified, only the + * specified types will be searched (searching for all interfaces will be disabled). *

- * This functionality was previously a private class of - * {@link MapperScannerConfigurer}, but was broken out in version 1.2.0. + * This functionality was previously a private class of {@link MapperScannerConfigurer}, but was broken out in version + * 1.2.0. * * @author Hunter Presnall * @author Eduardo Macarron + * * @see MapperFactoryBean + * * @since 1.2.0 */ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { + private static final Logger LOGGER = LoggerFactory.getLogger(ClassPathMapperScanner.class); + + // Copy of FactoryBean#OBJECT_TYPE_ATTRIBUTE which was added in Spring 5.2 + static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType"; + private boolean addToConfig = true; private boolean lazyInitialization; + private boolean printWarnLogIfNotFoundMappers = true; + private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; @@ -80,19 +89,130 @@ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { private String mapperHelperBeanName; - private MapperFactoryBean mapperFactoryBean = new MapperFactoryBean(); + private Class mapperFactoryBeanClass = MapperFactoryBean.class; + private String defaultScope; + private List excludeFilters; + + public ClassPathMapperScanner(BeanDefinitionRegistry registry, Environment environment) { + super(registry, false, environment); + setIncludeAnnotationConfig(!AotDetector.useGeneratedArtifacts()); + setPrintWarnLogIfNotFoundMappers(!NativeDetector.inNativeImage()); + } + + /** + * @deprecated Please use the {@link #ClassPathMapperScanner(BeanDefinitionRegistry, Environment)}. + */ + @Deprecated(since = "3.0.4", forRemoval = true) public ClassPathMapperScanner(BeanDefinitionRegistry registry) { super(registry, false); + setIncludeAnnotationConfig(!AotDetector.useGeneratedArtifacts()); + setPrintWarnLogIfNotFoundMappers(!NativeDetector.inNativeImage()); + } + + public void setAddToConfig(boolean addToConfig) { + this.addToConfig = addToConfig; + } + + public void setAnnotationClass(Class annotationClass) { + this.annotationClass = annotationClass; + } + + /** + * Set whether enable lazy initialization for mapper bean. + *

+ * Default is {@code false}. + *

+ * + * @param lazyInitialization + * Set the @{code true} to enable + * + * @since 2.0.2 + */ + public void setLazyInitialization(boolean lazyInitialization) { + this.lazyInitialization = lazyInitialization; + } + + /** + * Set whether print warning log if not found mappers that matches conditions. + *

+ * Default is {@code true}. But {@code false} when running in native image. + *

+ * + * @param printWarnLogIfNotFoundMappers + * Set the @{code true} to print + * + * @since 3.0.1 + */ + public void setPrintWarnLogIfNotFoundMappers(boolean printWarnLogIfNotFoundMappers) { + this.printWarnLogIfNotFoundMappers = printWarnLogIfNotFoundMappers; + } + + public void setMarkerInterface(Class markerInterface) { + this.markerInterface = markerInterface; + } + + public void setExcludeFilters(List excludeFilters) { + this.excludeFilters = excludeFilters; + } + + public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { + this.sqlSessionFactory = sqlSessionFactory; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + this.sqlSessionTemplate = sqlSessionTemplate; + } + + public void setSqlSessionTemplateBeanName(String sqlSessionTemplateBeanName) { + this.sqlSessionTemplateBeanName = sqlSessionTemplateBeanName; + } + + public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) { + this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName; + } + + /** + * @deprecated Since 2.0.1, Please use the {@link #setMapperFactoryBeanClass(Class)}. + */ + @Deprecated + public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) { + this.mapperFactoryBeanClass = mapperFactoryBean == null ? MapperFactoryBean.class : mapperFactoryBean.getClass(); + } + + /** + * Set the {@code MapperFactoryBean} class. + * + * @param mapperFactoryBeanClass + * the {@code MapperFactoryBean} class + * + * @since 2.0.1 + */ + public void setMapperFactoryBeanClass(Class mapperFactoryBeanClass) { + this.mapperFactoryBeanClass = mapperFactoryBeanClass == null ? MapperFactoryBean.class : mapperFactoryBeanClass; + } + + /** + * Set the default scope of scanned mappers. + *

+ * Default is {@code null} (equiv to singleton). + *

+ * + * @param defaultScope + * the scope + * + * @since 2.0.6 + */ + public void setDefaultScope(String defaultScope) { + this.defaultScope = defaultScope; } /** - * Configures parent scanner to search for the right interfaces. It can search - * for all interfaces or just for those that extends a markerInterface or/and - * those annotated with the annotationClass + * Configures parent scanner to search for the right interfaces. It can search for all interfaces or just for those + * that extends a markerInterface or/and those annotated with the annotationClass */ public void registerFilters() { - boolean acceptAllInterfaces = true; + var acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (this.annotationClass != null) { @@ -113,39 +233,40 @@ protected boolean matchClassName(String className) { if (acceptAllInterfaces) { // default include filter that accepts all classes - addIncludeFilter(new TypeFilter() { - @Override - public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { - return true; - } - }); + addIncludeFilter((metadataReader, metadataReaderFactory) -> true); } // exclude package-info.java - addExcludeFilter(new TypeFilter() { - @Override - public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { - String className = metadataReader.getClassMetadata().getClassName(); - if (className.endsWith("package-info")) { - return true; - } - return metadataReader.getAnnotationMetadata() - .hasAnnotation("tk.mybatis.mapper.annotation.RegisterMapper"); + addExcludeFilter((metadataReader, metadataReaderFactory) -> { + var className = metadataReader.getClassMetadata().getClassName(); + if (className.endsWith("package-info")) { + return true; } + return metadataReader.getAnnotationMetadata() + .hasAnnotation("tk.mybatis.mapper.annotation.RegisterMapper"); }); + + // exclude types declared by MapperScan.excludeFilters + if (excludeFilters != null && excludeFilters.size() > 0) { + for (TypeFilter excludeFilter : excludeFilters) { + addExcludeFilter(excludeFilter); + } + } } /** - * Calls the parent search that will search and register all the candidates. - * Then the registered objects are post processed to set them as - * MapperFactoryBeans + * Calls the parent search that will search and register all the candidates. Then the registered objects are post + * processed to set them as MapperFactoryBeans */ @Override public Set doScan(String... basePackages) { - Set beanDefinitions = super.doScan(basePackages); + var beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { - logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); + if (printWarnLogIfNotFoundMappers) { + LOGGER.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + + "' package. Please check your configuration."); + } } else { processBeanDefinitions(beanDefinitions); } @@ -154,19 +275,38 @@ public Set doScan(String... basePackages) { } private void processBeanDefinitions(Set beanDefinitions) { - GenericBeanDefinition definition; + AbstractBeanDefinition definition; + var registry = getRegistry(); for (BeanDefinitionHolder holder : beanDefinitions) { - definition = (GenericBeanDefinition) holder.getBeanDefinition(); - - if (logger.isDebugEnabled()) { - logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() - + "' and '" + definition.getBeanClassName() + "' mapperInterface"); + definition = (AbstractBeanDefinition) holder.getBeanDefinition(); + var scopedProxy = false; + if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) { + definition = (AbstractBeanDefinition) Optional + .ofNullable(((RootBeanDefinition) definition).getDecoratedDefinition()) + .map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException( + "The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]")); + scopedProxy = true; } + var beanClassName = definition.getBeanClassName(); + LOGGER.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + + "' mapperInterface"); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean - definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59 - definition.setBeanClass(this.mapperFactoryBean.getClass()); + definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 + try { + Class beanClass = Resources.classForName(beanClassName); + // Attribute for MockitoPostProcessor + // https://github.com/mybatis/spring-boot-starter/issues/475 + definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClass); + // for spring-native + definition.getPropertyValues().add("mapperInterface", beanClass); + } catch (ClassNotFoundException ignore) { + // ignore + } + + definition.setBeanClass(this.mapperFactoryBeanClass); + //设置通用 Mapper if (StringUtils.hasText(this.mapperHelperBeanName)) { definition.getPropertyValues().add("mapperHelper", new RuntimeBeanReference(this.mapperHelperBeanName)); @@ -180,9 +320,10 @@ private void processBeanDefinitions(Set beanDefinitions) { definition.getPropertyValues().add("addToConfig", this.addToConfig); - boolean explicitFactoryUsed = false; + var explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { - definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); + definition.getPropertyValues().add("sqlSessionFactory", + new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); @@ -191,50 +332,58 @@ private void processBeanDefinitions(Set beanDefinitions) { if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { - logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); + LOGGER.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } - definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); + definition.getPropertyValues().add("sqlSessionTemplate", + new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { - logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); + LOGGER.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { - if (logger.isDebugEnabled()) { - logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); - } + LOGGER.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } definition.setLazyInit(lazyInitialization); + + if (scopedProxy) { + continue; + } + + if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(definition.getScope()) && defaultScope != null) { + definition.setScope(defaultScope); + } + + if (!definition.isSingleton()) { + var proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true); + if (registry.containsBeanDefinition(proxyHolder.getBeanName())) { + registry.removeBeanDefinition(proxyHolder.getBeanName()); + } + registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition()); + } + } } - /** - * {@inheritDoc} - */ @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent(); } - /** - * {@inheritDoc} - */ @Override protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) { if (super.checkCandidate(beanName, beanDefinition)) { return true; - } else { - logger.warn("Skipping MapperFactoryBean with name '" + beanName - + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" - + ". Bean already defined with the same name!"); - return false; } + LOGGER.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); + return false; } public MapperHelper getMapperHelper() { @@ -245,18 +394,6 @@ public void setMapperHelper(MapperHelper mapperHelper) { this.mapperHelper = mapperHelper; } - public void setAddToConfig(boolean addToConfig) { - this.addToConfig = addToConfig; - } - - public void setAnnotationClass(Class annotationClass) { - this.annotationClass = annotationClass; - } - - public void setLazyInitialization(boolean lazyInitialization) { - this.lazyInitialization = lazyInitialization; - } - /** * 配置通用 Mapper * @@ -269,16 +406,12 @@ public void setConfig(Config config) { mapperHelper.setConfig(config); } - public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) { - this.mapperFactoryBean = mapperFactoryBean != null ? mapperFactoryBean : new MapperFactoryBean(); - } - public void setMapperHelperBeanName(String mapperHelperBeanName) { this.mapperHelperBeanName = mapperHelperBeanName; } /** - * 从环境变量中获取 mapper 配置信息 + * TODO 从环境变量中获取 mapper 配置信息 * * @param environment */ @@ -293,7 +426,7 @@ public void setMapperProperties(Environment environment) { } /** - * 从 properties 数组获取 mapper 配置信息 + * TODO 从 properties 数组获取 mapper 配置信息 * * @param properties */ @@ -319,23 +452,4 @@ public void setMapperProperties(String[] properties) { mapperHelper.setProperties(props); } - public void setMarkerInterface(Class markerInterface) { - this.markerInterface = markerInterface; - } - - public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { - this.sqlSessionFactory = sqlSessionFactory; - } - - public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) { - this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName; - } - - public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { - this.sqlSessionTemplate = sqlSessionTemplate; - } - - public void setSqlSessionTemplateBeanName(String sqlSessionTemplateBeanName) { - this.sqlSessionTemplateBeanName = sqlSessionTemplateBeanName; - } } diff --git a/spring/src/main/java/tk/mybatis/spring/mapper/MapperScannerConfigurer.java b/spring/src/main/java/tk/mybatis/spring/mapper/MapperScannerConfigurer.java index 70970e278..3c0b1d715 100644 --- a/spring/src/main/java/tk/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/spring/src/main/java/tk/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -1,12 +1,12 @@ -/** - * Copyright 2010-2016 the original author or authors. - *

+/* + * Copyright 2010-2024 the original author or authors. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * https://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,11 +17,10 @@ import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; -import org.springframework.beans.PropertyValue; +import org.springframework.beans.BeanUtils; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyResourceConfigurer; import org.springframework.beans.factory.config.TypedStringValue; @@ -33,69 +32,70 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; +import org.springframework.core.type.filter.*; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.common.Marker; +import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; import java.lang.annotation.Annotation; -import java.util.Map; -import java.util.Properties; +import java.util.*; +import java.util.regex.Pattern; import static org.springframework.util.Assert.notNull; /** - * BeanDefinitionRegistryPostProcessor that searches recursively starting from a base package for - * interfaces and registers them as {@code MapperFactoryBean}. Note that only interfaces with at - * least one method will be registered; concrete classes will be ignored. + * BeanDefinitionRegistryPostProcessor that searches recursively starting from a base package for interfaces and + * registers them as {@code MapperFactoryBean}. Note that only interfaces with at least one method will be registered; + * concrete classes will be ignored. *

* This class was a {code BeanFactoryPostProcessor} until 1.0.1 version. It changed to - * {@code BeanDefinitionRegistryPostProcessor} in 1.0.2. See https://jira.springsource.org/browse/SPR-8269 - * for the details. + * {@code BeanDefinitionRegistryPostProcessor} in 1.0.2. See https://jira.springsource.org/browse/SPR-8269 for the + * details. *

- * The {@code basePackage} property can contain more than one package name, separated by either - * commas or semicolons. + * The {@code basePackage} property can contain more than one package name, separated by either commas or semicolons. *

- * This class supports filtering the mappers created by either specifying a marker interface or an - * annotation. The {@code annotationClass} property specifies an annotation to search for. The - * {@code markerInterface} property specifies a parent interface to search for. If both properties - * are specified, mappers are added for interfaces that match either criteria. By default, - * these two properties are null, so all interfaces in the given {@code basePackage} are added as - * mappers. + * This class supports filtering the mappers created by either specifying a marker interface or an annotation. The + * {@code annotationClass} property specifies an annotation to search for. The {@code markerInterface} property + * specifies a parent interface to search for. If both properties are specified, mappers are added for interfaces that + * match either criteria. By default, these two properties are null, so all interfaces in the given + * {@code basePackage} are added as mappers. *

- * This configurer enables autowire for all the beans that it creates so that they are - * automatically autowired with the proper {@code SqlSessionFactory} or {@code SqlSessionTemplate}. - * If there is more than one {@code SqlSessionFactory} in the application, however, autowiring - * cannot be used. In this case you must explicitly specify either an {@code SqlSessionFactory} or - * an {@code SqlSessionTemplate} to use via the bean name properties. Bean names are used - * rather than actual objects because Spring does not initialize property placeholders until after - * this class is processed. + * This configurer enables autowire for all the beans that it creates so that they are automatically autowired with the + * proper {@code SqlSessionFactory} or {@code SqlSessionTemplate}. If there is more than one {@code SqlSessionFactory} + * in the application, however, autowiring cannot be used. In this case you must explicitly specify either an + * {@code SqlSessionFactory} or an {@code SqlSessionTemplate} to use via the bean name properties. Bean names + * are used rather than actual objects because Spring does not initialize property placeholders until after this class + * is processed. *

- * Passing in an actual object which may require placeholders (i.e. DB user password) will fail. - * Using bean names defers actual object creation until later in the startup - * process, after all placeholder substituation is completed. However, note that this configurer - * does support property placeholders of its own properties. The basePackage - * and bean name properties all support ${property} style substitution. + * Passing in an actual object which may require placeholders (i.e. DB user password) will fail. Using bean names defers + * actual object creation until later in the startup process, after all placeholder substitution is completed. However, + * note that this configurer does support property placeholders of its own properties. The + * basePackage and bean name properties all support ${property} style substitution. *

* Configuration sample: - *

- *

+ * *

  * {@code
- * 
- * 
- * 
- * 
- * 
+ *   
+ *       
+ *       
+ *       
+ *   
  * }
  * 
* * @author Hunter Presnall * @author Eduardo Macarron - * @author liuzh - * @see tk.mybatis.spring.mapper.MapperFactoryBean + * + * @see MapperFactoryBean * @see ClassPathMapperScanner */ -public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { +public class MapperScannerConfigurer + implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { private String basePackage; @@ -115,6 +115,12 @@ public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProces private Class markerInterface; + private List excludeFilters; + + private List> rawExcludeFilters; + + private Class mapperFactoryBeanClass; + private ApplicationContext applicationContext; private String beanName; @@ -123,8 +129,12 @@ public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProces private BeanNameGenerator nameGenerator; + private String defaultScope; + private MapperHelper mapperHelper = new MapperHelper(); + private String mapperHelperBeanName; + public MapperHelper getMapperHelper() { return mapperHelper; } @@ -135,132 +145,25 @@ public void setMapperHelper(MapperHelper mapperHelper) { /** - * {@inheritDoc} - */ - @Override - public void afterPropertiesSet() throws Exception { - notNull(this.basePackage, "Property 'basePackage' is required"); - } - - /** - * {@inheritDoc} - */ - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { - // left intentionally blank - } - - /** - * {@inheritDoc} - * - * @since 1.0.2 - */ - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { - if (this.processPropertyPlaceHolders) { - processPropertyPlaceHolders(); - } - ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); - scanner.setAddToConfig(this.addToConfig); - scanner.setAnnotationClass(this.annotationClass); - scanner.setMarkerInterface(this.markerInterface); - scanner.setSqlSessionFactory(this.sqlSessionFactory); - scanner.setSqlSessionTemplate(this.sqlSessionTemplate); - scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); - scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); - scanner.setResourceLoader(this.applicationContext); - scanner.setBeanNameGenerator(this.nameGenerator); - if (StringUtils.hasText(lazyInitialization)) { - scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); - } - scanner.registerFilters(); - //设置通用 Mapper - scanner.setMapperHelper(this.mapperHelper); - scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); - } - - /* - * BeanDefinitionRegistries are called early in application startup, before - * BeanFactoryPostProcessors. This means that PropertyResourceConfigurers will not have been - * loaded and any property substitution of this class' properties will fail. To avoid this, find - * any PropertyResourceConfigurers defined in the context and run them on this class' bean - * definition. Then update the values. - */ - private void processPropertyPlaceHolders() { - Map prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class); - - if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) { - BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) applicationContext) - .getBeanFactory().getBeanDefinition(beanName); - - // PropertyResourceConfigurer does not expose any methods to explicitly perform - // property placeholder substitution. Instead, create a BeanFactory that just - // contains this mapper scanner and post process the factory. - DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); - factory.registerBeanDefinition(beanName, mapperScannerBean); - - for (PropertyResourceConfigurer prc : prcs.values()) { - prc.postProcessBeanFactory(factory); - } - - PropertyValues values = mapperScannerBean.getPropertyValues(); - - this.basePackage = updatePropertyValue("basePackage", values); - this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values); - this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values); - this.lazyInitialization = updatePropertyValue("lazyInitialization", values); - } - this.lazyInitialization = this.lazyInitialization == null ? null : getEnvironment().resolvePlaceholders(this.lazyInitialization); - } - - private Environment getEnvironment() { - return this.applicationContext.getEnvironment(); - } - - private String updatePropertyValue(String propertyName, PropertyValues values) { - PropertyValue property = values.getPropertyValue(propertyName); - - if (property == null) { - return null; - } - - Object value = property.getValue(); - - if (value == null) { - return null; - } else if (value instanceof String) { - return value.toString(); - } else if (value instanceof TypedStringValue) { - return ((TypedStringValue) value).getValue(); - } else { - return null; - } - } - - /** - * Gets beanNameGenerator to be used while running the scanner. - * - * @return the beanNameGenerator BeanNameGenerator that has been configured - * @since 1.2.0 - */ - public BeanNameGenerator getNameGenerator() { - return nameGenerator; - } - - /** - * Sets beanNameGenerator to be used while running the scanner. + * This property lets you set the base package for your mapper interface files. + *

+ * You can set more than one package by using a semicolon or comma as a separator. + *

+ * Mappers will be searched for recursively starting in the specified package(s). * - * @param nameGenerator the beanNameGenerator to set - * @since 1.2.0 + * @param basePackage + * base package name */ - public void setNameGenerator(BeanNameGenerator nameGenerator) { - this.nameGenerator = nameGenerator; + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; } /** * Same as {@code MapperFactoryBean#setAddToConfig(boolean)}. * * @param addToConfig + * a flag that whether add mapper to MyBatis or not + * * @see MapperFactoryBean#setAddToConfig(boolean) */ public void setAddToConfig(boolean addToConfig) { @@ -269,8 +172,14 @@ public void setAddToConfig(boolean addToConfig) { /** * Set whether enable lazy initialization for mapper bean. + *

* Default is {@code false}. - * @param lazyInitialization Set the @{code true} to enable + *

+ * + * @param lazyInitialization + * Set the @{code true} to enable + * + * @since 2.0.2 */ public void setLazyInitialization(String lazyInitialization) { this.lazyInitialization = lazyInitialization; @@ -279,79 +188,112 @@ public void setLazyInitialization(String lazyInitialization) { /** * This property specifies the annotation that the scanner will search for. *

- * The scanner will register all interfaces in the base package that also have the - * specified annotation. + * The scanner will register all interfaces in the base package that also have the specified annotation. *

* Note this can be combined with markerInterface. * - * @param annotationClass annotation class + * @param annotationClass + * annotation class */ public void setAnnotationClass(Class annotationClass) { this.annotationClass = annotationClass; } /** - * {@inheritDoc} + * This property specifies the parent that the scanner will search for. + *

+ * The scanner will register all interfaces in the base package that also have the specified interface class as a + * parent. + *

+ * Note this can be combined with annotationClass. + * + * @param superClass + * parent class */ - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; + public void setMarkerInterface(Class superClass) { + this.markerInterface = superClass; + if (Marker.class.isAssignableFrom(superClass)) { + mapperHelper.registerMapper(superClass); + } } /** - * This property lets you set the base package for your mapper interface files. + * Specifies which types are not eligible for the mapper scanner. *

- * You can set more than one package by using a semicolon or comma as a separator. - *

- * Mappers will be searched for recursively starting in the specified package(s). + * The scanner will exclude types that define with excludeFilters. * - * @param basePackage base package name + * @since 3.0.3 + * + * @param excludeFilters + * list of TypeFilter */ - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; + public void setExcludeFilters(List excludeFilters) { + this.excludeFilters = excludeFilters; } /** - * {@inheritDoc} + * In order to support process PropertyPlaceHolders. + *

+ * After parsed, it will be added to excludeFilters. + * + * @since 3.0.3 + * + * @param rawExcludeFilters + * list of rawExcludeFilter */ - @Override - public void setBeanName(String name) { - this.beanName = name; + public void setRawExcludeFilters(List> rawExcludeFilters) { + this.rawExcludeFilters = rawExcludeFilters; } /** - * This property specifies the parent that the scanner will search for. + * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. *

- * The scanner will register all interfaces in the base package that also have the - * specified interface class as a parent. + * + * @deprecated Use {@link #setSqlSessionTemplateBeanName(String)} instead + * + * @param sqlSessionTemplate + * a template of SqlSession + */ + @Deprecated + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + this.sqlSessionTemplate = sqlSessionTemplate; + } + + /** + * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. *

- * Note this can be combined with annotationClass. + * Note bean names are used, not bean references. This is because the scanner loads early during the start process and + * it is too early to build mybatis object instances. * - * @param superClass parent class + * @since 1.1.0 + * + * @param sqlSessionTemplateName + * Bean name of the {@code SqlSessionTemplate} */ - public void setMarkerInterface(Class superClass) { - this.markerInterface = superClass; - if (Marker.class.isAssignableFrom(superClass)) { - mapperHelper.registerMapper(superClass); - } + public void setSqlSessionTemplateBeanName(String sqlSessionTemplateName) { + this.sqlSessionTemplateBeanName = sqlSessionTemplateName; } /** - * @param processPropertyPlaceHolders - * @since 1.1.1 + * 属性注入 + * + * @param properties */ - public void setProcessPropertyPlaceHolders(boolean processPropertyPlaceHolders) { - this.processPropertyPlaceHolders = processPropertyPlaceHolders; + public void setProperties(Properties properties) { + mapperHelper.setProperties(properties); } /** - * Specifies which {@code SqlSessionFactory} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. *

* - * @param sqlSessionFactory * @deprecated Use {@link #setSqlSessionFactoryBeanName(String)} instead. + * + * @param sqlSessionFactory + * a factory of SqlSession */ @Deprecated public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { @@ -359,58 +301,315 @@ public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { } /** - * Specifies which {@code SqlSessionFactory} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context. + * Usually this is only needed when you have more than one datasource. *

- * Note bean names are used, not bean references. This is because the scanner - * loads early during the start process and it is too early to build mybatis - * object instances. + * Note bean names are used, not bean references. This is because the scanner loads early during the start process and + * it is too early to build mybatis object instances. * - * @param sqlSessionFactoryName Bean name of the {@code SqlSessionFactory} * @since 1.1.0 + * + * @param sqlSessionFactoryName + * Bean name of the {@code SqlSessionFactory} */ public void setSqlSessionFactoryBeanName(String sqlSessionFactoryName) { this.sqlSessionFactoryBeanName = sqlSessionFactoryName; } /** - * Specifies which {@code SqlSessionTemplate} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Specifies a flag that whether execute a property placeholder processing or not. *

+ * The default is {@literal false}. This means that a property placeholder processing does not execute. * - * @param sqlSessionTemplate - * @deprecated Use {@link #setSqlSessionTemplateBeanName(String)} instead + * @since 1.1.1 + * + * @param processPropertyPlaceHolders + * a flag that whether execute a property placeholder processing or not */ - @Deprecated - public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { - this.sqlSessionTemplate = sqlSessionTemplate; + public void setProcessPropertyPlaceHolders(boolean processPropertyPlaceHolders) { + this.processPropertyPlaceHolders = processPropertyPlaceHolders; + } + + /** + * The class of the {@link MapperFactoryBean} to return a mybatis proxy as spring bean. + * + * @param mapperFactoryBeanClass + * The class of the MapperFactoryBean + * + * @since 2.0.1 + */ + public void setMapperFactoryBeanClass(Class mapperFactoryBeanClass) { + this.mapperFactoryBeanClass = mapperFactoryBeanClass; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Override + public void setBeanName(String name) { + this.beanName = name; + } + + /** + * Gets beanNameGenerator to be used while running the scanner. + * + * @return the beanNameGenerator BeanNameGenerator that has been configured + * + * @since 1.2.0 + */ + public BeanNameGenerator getNameGenerator() { + return nameGenerator; } /** - * Specifies which {@code SqlSessionTemplate} to use in the case that there is - * more than one in the spring context. Usually this is only needed when you - * have more than one datasource. + * Sets beanNameGenerator to be used while running the scanner. + * + * @param nameGenerator + * the beanNameGenerator to set + * + * @since 1.2.0 + */ + public void setNameGenerator(BeanNameGenerator nameGenerator) { + this.nameGenerator = nameGenerator; + } + + /** + * Sets the default scope of scanned mappers. *

- * Note bean names are used, not bean references. This is because the scanner - * loads early during the start process and it is too early to build mybatis - * object instances. + * Default is {@code null} (equiv to singleton). + *

* - * @param sqlSessionTemplateName Bean name of the {@code SqlSessionTemplate} - * @since 1.1.0 + * @param defaultScope + * the default scope + * + * @since 2.0.6 */ - public void setSqlSessionTemplateBeanName(String sqlSessionTemplateName) { - this.sqlSessionTemplateBeanName = sqlSessionTemplateName; + public void setDefaultScope(String defaultScope) { + this.defaultScope = defaultScope; + } + + @Override + public void afterPropertiesSet() throws Exception { + notNull(this.basePackage, "Property 'basePackage' is required"); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + // left intentionally blank + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { + if (this.processPropertyPlaceHolders) { + processPropertyPlaceHolders(); + } + + var scanner = new ClassPathMapperScanner(registry, getEnvironment()); + scanner.setAddToConfig(this.addToConfig); + scanner.setAnnotationClass(this.annotationClass); + scanner.setMarkerInterface(this.markerInterface); + scanner.setExcludeFilters(this.excludeFilters = mergeExcludeFilters()); + scanner.setSqlSessionFactory(this.sqlSessionFactory); + scanner.setSqlSessionTemplate(this.sqlSessionTemplate); + scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); + scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); + scanner.setResourceLoader(this.applicationContext); + scanner.setBeanNameGenerator(this.nameGenerator); + scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass); + if (StringUtils.hasText(lazyInitialization)) { + scanner.setLazyInitialization(Boolean.parseBoolean(lazyInitialization)); + } + if (StringUtils.hasText(defaultScope)) { + scanner.setDefaultScope(defaultScope); + } + if (StringUtils.hasText(mapperHelperBeanName)) { + scanner.setMapperHelperBeanName(mapperHelperBeanName); + } + scanner.registerFilters(); + //设置通用 Mapper + scanner.setMapperHelper(this.mapperHelper); + scanner.scan( + StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); + } + + /* + * BeanDefinitionRegistries are called early in application startup, before BeanFactoryPostProcessors. This means that + * PropertyResourceConfigurers will not have been loaded and any property substitution of this class' properties will + * fail. To avoid this, find any PropertyResourceConfigurers defined in the context and run them on this class' bean + * definition. Then update the values. + */ + private void processPropertyPlaceHolders() { + Map prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class, + false, false); + + if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) { + var mapperScannerBean = ((ConfigurableApplicationContext) applicationContext).getBeanFactory() + .getBeanDefinition(beanName); + + // PropertyResourceConfigurer does not expose any methods to explicitly perform + // property placeholder substitution. Instead, create a BeanFactory that just + // contains this mapper scanner and post process the factory. + var factory = new DefaultListableBeanFactory(); + factory.registerBeanDefinition(beanName, mapperScannerBean); + + for (PropertyResourceConfigurer prc : prcs.values()) { + prc.postProcessBeanFactory(factory); + } + + PropertyValues values = mapperScannerBean.getPropertyValues(); + + this.basePackage = getPropertyValue("basePackage", values); + this.sqlSessionFactoryBeanName = getPropertyValue("sqlSessionFactoryBeanName", values); + this.sqlSessionTemplateBeanName = getPropertyValue("sqlSessionTemplateBeanName", values); + this.lazyInitialization = getPropertyValue("lazyInitialization", values); + this.defaultScope = getPropertyValue("defaultScope", values); + this.rawExcludeFilters = getPropertyValueForTypeFilter("rawExcludeFilters", values); + } + this.basePackage = Optional.ofNullable(this.basePackage).map(getEnvironment()::resolvePlaceholders).orElse(null); + this.sqlSessionFactoryBeanName = Optional.ofNullable(this.sqlSessionFactoryBeanName) + .map(getEnvironment()::resolvePlaceholders).orElse(null); + this.sqlSessionTemplateBeanName = Optional.ofNullable(this.sqlSessionTemplateBeanName) + .map(getEnvironment()::resolvePlaceholders).orElse(null); + this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders) + .orElse(null); + this.defaultScope = Optional.ofNullable(this.defaultScope).map(getEnvironment()::resolvePlaceholders).orElse(null); + } + + private Environment getEnvironment() { + return this.applicationContext.getEnvironment(); + } + + private String getPropertyValue(String propertyName, PropertyValues values) { + var property = values.getPropertyValue(propertyName); + + if (property == null) { + return null; + } + + var value = property.getValue(); + + if (value == null) { + return null; + } + if (value instanceof String) { + return value.toString(); + } + if (value instanceof TypedStringValue) { + return ((TypedStringValue) value).getValue(); + } + return null; + } + + @SuppressWarnings("unchecked") + private List> getPropertyValueForTypeFilter(String propertyName, PropertyValues values) { + var property = values.getPropertyValue(propertyName); + Object value; + if (property == null || (value = property.getValue()) == null || !(value instanceof List)) { + return null; + } + return (List>) value; + } + + private List mergeExcludeFilters() { + List typeFilters = new ArrayList<>(); + if (this.rawExcludeFilters == null || this.rawExcludeFilters.isEmpty()) { + return this.excludeFilters; + } + if (this.excludeFilters != null && !this.excludeFilters.isEmpty()) { + typeFilters.addAll(this.excludeFilters); + } + try { + for (Map typeFilter : this.rawExcludeFilters) { + typeFilters.add( + createTypeFilter(typeFilter.get("type"), typeFilter.get("expression"), this.getClass().getClassLoader())); + } + } catch (ClassNotFoundException exception) { + throw new RuntimeException("ClassNotFoundException occur when to load the Specified excludeFilter classes.", + exception); + } + return typeFilters; + } + + @SuppressWarnings("unchecked") + private TypeFilter createTypeFilter(String filterType, String expression, @Nullable ClassLoader classLoader) + throws ClassNotFoundException { + + if (this.processPropertyPlaceHolders) { + expression = this.getEnvironment().resolvePlaceholders(expression); + } + + switch (filterType) { + case "annotation": + Class filterAnno = ClassUtils.forName(expression, classLoader); + if (!Annotation.class.isAssignableFrom(filterAnno)) { + throw new IllegalArgumentException( + "Class is not assignable to [" + Annotation.class.getName() + "]: " + expression); + } + return new AnnotationTypeFilter((Class) filterAnno); + case "custom": + Class filterClass = ClassUtils.forName(expression, classLoader); + if (!TypeFilter.class.isAssignableFrom(filterClass)) { + throw new IllegalArgumentException( + "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); + } + return (TypeFilter) BeanUtils.instantiateClass(filterClass); + case "assignable": + return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); + case "regex": + return new RegexPatternTypeFilter(Pattern.compile(expression)); + case "aspectj": + return new AspectJTypeFilter(expression, classLoader); + default: + throw new IllegalArgumentException("Unsupported filter type: " + filterType); + } + } + + public void setMapperHelperBeanName(String mapperHelperBeanName) { + this.mapperHelperBeanName = mapperHelperBeanName; } /** - * 属性注入 + * 从环境变量中获取 mapper 配置信息 + * + * @param environment + */ + public void setMapperProperties(Environment environment) { + Config config = SpringBootBindUtil.bind(environment, Config.class, Config.PREFIX); + if (mapperHelper == null) { + mapperHelper = new MapperHelper(); + } + if (config != null) { + mapperHelper.setConfig(config); + } + } + + /** + * 从 properties 数组获取 mapper 配置信息 * * @param properties */ - public void setProperties(Properties properties) { - mapperHelper.setProperties(properties); + public void setMapperProperties(String[] properties) { + if (mapperHelper == null) { + mapperHelper = new MapperHelper(); + } + Properties props = new Properties(); + for (String property : properties) { + property = property.trim(); + int index = property.indexOf("="); + if (index < 0) { + throw new MapperException("通过 @MapperScan 注解的 properties 参数配置出错:" + property + " !\n" + + "请保证配置项按 properties 文件格式要求进行配置,例如:\n" + + "properties = {\n" + + "\t\"mappers=tk.mybatis.mapper.common.Mapper\",\n" + + "\t\"notEmpty=true\"\n" + + "}" + ); + } + props.put(property.substring(0, index).trim(), property.substring(index + 1).trim()); + } + mapperHelper.setProperties(props); } } diff --git a/spring/src/main/java/tk/mybatis/spring/mapper/SpringBootBindUtil.java b/spring/src/main/java/tk/mybatis/spring/mapper/SpringBootBindUtil.java index de49c343b..34a4ae9d3 100644 --- a/spring/src/main/java/tk/mybatis/spring/mapper/SpringBootBindUtil.java +++ b/spring/src/main/java/tk/mybatis/spring/mapper/SpringBootBindUtil.java @@ -24,14 +24,11 @@ package tk.mybatis.spring.mapper; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValues; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; -import org.springframework.core.env.PropertyResolver; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.util.Map; /** * @author liuzh @@ -39,99 +36,20 @@ */ public abstract class SpringBootBindUtil { - public static final IBind BIND; + private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootBindUtil.class); - static { - IBind bind; + public static T bind(Environment environment, Class targetClass, String prefix) { try { - //boot2 - Class.forName("org.springframework.boot.context.properties.bind.Binder"); - bind = new SpringBoot2Bind(); + Class binderClass = Class.forName("org.springframework.boot.context.properties.bind.Binder"); + Method getMethod = binderClass.getDeclaredMethod("get", Environment.class); + Method bindMethod = binderClass.getDeclaredMethod("bind", String.class, Class.class); + Object binder = getMethod.invoke(null, environment); + Object bindResult = bindMethod.invoke(binder, prefix, targetClass); + Method getMethodResult = bindResult.getClass().getDeclaredMethod("get"); + return (T) getMethodResult.invoke(bindResult); } catch (Exception e) { - //boot1 - bind = new SpringBoot1Bind(); - } - BIND = bind; - } - - public static T bind(Environment environment, Class targetClass, String prefix) { - return BIND.bind(environment, targetClass, prefix); - } - - public interface IBind { - T bind(Environment environment, Class targetClass, String prefix); - } - - /** - * 使用 Spring Boot 1.x 方式绑定 - */ - public static class SpringBoot1Bind implements IBind { - @Override - public T bind(Environment environment, Class targetClass, String prefix) { - /** - 为了方便以后直接依赖 Spring Boot 2.x 时不需要改动代码,这里也使用反射 - try { - RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment); - Map properties = resolver.getSubProperties(""); - T target = targetClass.newInstance(); - RelaxedDataBinder binder = new RelaxedDataBinder(target, prefix); - binder.bind(new MutablePropertyValues(properties)); - return target; - } catch (Exception e) { - throw new RuntimeException(e); - } - 下面是这段代码的反射实现 - */ - try { - //反射提取配置信息 - Class resolverClass = Class.forName("org.springframework.boot.bind.RelaxedPropertyResolver"); - Constructor resolverConstructor = resolverClass.getDeclaredConstructor(PropertyResolver.class); - Method getSubPropertiesMethod = resolverClass.getDeclaredMethod("getSubProperties", String.class); - Object resolver = resolverConstructor.newInstance(environment); - Map properties = (Map) getSubPropertiesMethod.invoke(resolver, ""); - //创建结果类 - T target = targetClass.newInstance(); - //反射使用 org.springframework.boot.bind.RelaxedDataBinder - Class binderClass = Class.forName("org.springframework.boot.bind.RelaxedDataBinder"); - Constructor binderConstructor = binderClass.getDeclaredConstructor(Object.class, String.class); - Method bindMethod = binderClass.getMethod("bind", PropertyValues.class); - //创建 binder 并绑定数据 - Object binder = binderConstructor.newInstance(target, prefix); - bindMethod.invoke(binder, new MutablePropertyValues(properties)); - return target; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - /** - * 使用 Spring Boot 2.x 方式绑定 - */ - public static class SpringBoot2Bind implements IBind { - @Override - public T bind(Environment environment, Class targetClass, String prefix) { - /** - 由于不能同时依赖不同的两个版本,所以使用反射实现下面的代码 - Binder binder = Binder.get(environment); - return binder.bind(prefix, targetClass).get(); - 下面是这两行代码的完全反射版本 - */ - try { - Class bindClass = Class.forName("org.springframework.boot.context.properties.bind.Binder"); - Method getMethod = bindClass.getDeclaredMethod("get", Environment.class); - Method bindMethod = bindClass.getDeclaredMethod("bind", String.class, Class.class); - Object bind = getMethod.invoke(null, environment); - Object bindResult = bindMethod.invoke(bind, prefix, targetClass); - Method resultGetMethod = bindResult.getClass().getDeclaredMethod("get"); - Method isBoundMethod = bindResult.getClass().getDeclaredMethod("isBound"); - if ((Boolean) isBoundMethod.invoke(bindResult)) { - return (T) resultGetMethod.invoke(bindResult); - } - return null; - } catch (Exception e) { - throw new RuntimeException(e); - } + LOGGER.warn("Bind " + targetClass + " error", e); + return null; } } diff --git a/spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java b/spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java index fe273f3e0..3169b5041 100644 --- a/spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java +++ b/spring/src/test/java/tk/mybatis/mapper/annotation/SpringAnnotationTest.java @@ -10,7 +10,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.entity.Config; import tk.mybatis.mapper.mapperhelper.MapperHelper; @@ -70,7 +69,7 @@ public void testMyBatisConfiguration() { Assert.assertEquals(183, countries.size()); } - @Test(expected = MapperException.class) + @Test(expected = Exception.class) public void testMyBatisConfigPropertiesError() { applicationContext.register(MyBatisConfigPropertiesError.class); startContext(); From 991b693ffbdbb6bfd0e9ac9e08ee2f74c9b03657 Mon Sep 17 00:00:00 2001 From: liuzh Date: Mon, 19 Aug 2024 23:45:55 +0800 Subject: [PATCH 4/8] 5.0.0-rc1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b6ea3b8f6..41868225d 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ https://mybatis.io - 5.0.0-SNAPSHOT + 5.0.0-rc1 17 17 UTF-8 From bf0474fb977344f6c056f7165bc11bf55bcc43ac Mon Sep 17 00:00:00 2001 From: liuzh Date: Mon, 19 Aug 2024 23:53:51 +0800 Subject: [PATCH 5/8] github action jdk17 --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e954b254..e9281dc66 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Maven Central Repository uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '17' distribution: 'adopt' server-id: ossrh server-username: MAVEN_USERNAME diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 460dee580..60185440c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Maven Central Repository uses: actions/setup-java@v2 with: - java-version: '8' + java-version: '17' distribution: 'adopt' - name: Run the Maven verify phase run: mvn --batch-mode --update-snapshots -P dev test \ No newline at end of file From 50cfbab79b36283f9b91d900dfe568cdbe2d1ece Mon Sep 17 00:00:00 2001 From: liuzh Date: Tue, 20 Aug 2024 21:27:04 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=AE=8C=E5=96=84spring=20boot=E9=9B=86?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 39 +- .../mapper-spring-boot-autoconfigure/pom.xml | 16 + .../MapperAutoConfiguration.java | 251 ++++++--- ...pendsOnDatabaseInitializationDetector.java | 24 + ...ybatisLanguageDriverAutoConfiguration.java | 136 +++++ .../autoconfigure/MybatisProperties.java | 529 +++++++++++++++++- .../mapper/autoconfigure/SpringBootVFS.java | 80 ++- .../SqlSessionFactoryBeanCustomizer.java | 21 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/application.properties | 6 +- .../src/main/resources/logback.xml | 10 + .../mybatis/sample/SampleXmlApplication.java | 2 + .../src/main/resources/application.yml | 2 + .../src/main/resources/logback.xml | 10 + .../spring/annotation/MapperScans.java | 8 +- 15 files changed, 982 insertions(+), 153 deletions(-) create mode 100644 spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisDependsOnDatabaseInitializationDetector.java create mode 100644 spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisLanguageDriverAutoConfiguration.java create mode 100644 spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SqlSessionFactoryBeanCustomizer.java create mode 100644 spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/logback.xml create mode 100644 spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/logback.xml diff --git a/pom.xml b/pom.xml index 41868225d..da994339a 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ https://mybatis.io - 5.0.0-rc1 + 5.0.0-SNAPSHOT 17 17 UTF-8 @@ -44,10 +44,14 @@ 3.1.0 2.0.16 3.5.16 + 1.2.4 + 2.1.2 + 1.0.4 + 4.13.2 2.7.3 - 1.5.7 + 1.5.6 @@ -78,10 +82,35 @@ mybatis ${mybatis.version} + + org.mybatis.scripting + mybatis-freemarker + ${mybatis-freemarker.version} + true + + + org.mybatis.scripting + mybatis-velocity + ${mybatis-velocity.version} + true + + + org.mybatis.scripting + mybatis-thymeleaf + ${mybatis-thymeleaf.version} + true + org.slf4j slf4j-api ${slf4j.version} + true + + + ch.qos.logback + logback-classic + ${logback.version} + true @@ -91,12 +120,6 @@ ${junit.version} test - - ch.qos.logback - logback-classic - ${logback.version} - test - org.hsqldb hsqldb diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml b/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml index 7b9be7921..97e10a6ad 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/pom.xml @@ -41,6 +41,22 @@ spring-boot-autoconfigure + + org.mybatis.scripting + mybatis-freemarker + true + + + org.mybatis.scripting + mybatis-velocity + true + + + org.mybatis.scripting + mybatis-thymeleaf + true + + tk.mybatis mapper-core diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java index 344bbdd5d..b6c587bda 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java @@ -1,35 +1,50 @@ -/** - * Copyright 2015-2018 the original author or authors. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package tk.mybatis.mapper.autoconfigure; +import java.beans.PropertyDescriptor; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.sql.DataSource; + import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.mapping.DatabaseIdProvider; import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.TypeHandler; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -54,35 +69,26 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import tk.mybatis.spring.annotation.BaseProperties; -import tk.mybatis.spring.mapper.ClassPathMapperScanner; import tk.mybatis.spring.mapper.MapperFactoryBean; -import tk.mybatis.spring.mapper.SpringBootBindUtil; - -import javax.sql.DataSource; -import java.util.Arrays; -import java.util.List; +import tk.mybatis.spring.mapper.MapperScannerConfigurer; /** - * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a - * {@link SqlSessionFactory} and a {@link SqlSessionTemplate}. - * - * If {@link org.mybatis.spring.annotation.MapperScan} is used, or a - * configuration file is specified as a property, those will be considered, - * otherwise this auto-configuration will attempt to register mappers based on - * the interface definitions in or under the root auto-configuration package. + * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a {@link SqlSessionFactory} and a + * {@link SqlSessionTemplate}. If {@link tk.mybatis.spring.annotation.MapperScan} is used, or a configuration file is + * specified as a property, those will be considered, otherwise this auto-configuration will attempt to register mappers + * based on the interface definitions in or under the root auto-configuration package. * * @author Eddú Meléndez * @author Josh Long * @author Kazuki Shimizu * @author Eduardo Macarrón */ -@org.springframework.context.annotation.Configuration +@org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class}) @ConditionalOnSingleCandidate(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) -@AutoConfigureAfter(DataSourceAutoConfiguration.class) @AutoConfigureBefore(name = "org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration") +@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class}) public class MapperAutoConfiguration implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(MapperAutoConfiguration.class); @@ -91,22 +97,31 @@ public class MapperAutoConfiguration implements InitializingBean { private final Interceptor[] interceptors; + private final TypeHandler[] typeHandlers; + + private final LanguageDriver[] languageDrivers; + private final ResourceLoader resourceLoader; private final DatabaseIdProvider databaseIdProvider; private final List configurationCustomizers; - public MapperAutoConfiguration(MybatisProperties properties, - ObjectProvider interceptorsProvider, - ResourceLoader resourceLoader, - ObjectProvider databaseIdProvider, - ObjectProvider> configurationCustomizersProvider) { + private final List sqlSessionFactoryBeanCustomizers; + + public MapperAutoConfiguration(MybatisProperties properties, ObjectProvider interceptorsProvider, + ObjectProvider typeHandlersProvider, ObjectProvider languageDriversProvider, + ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, + ObjectProvider> configurationCustomizersProvider, + ObjectProvider> sqlSessionFactoryBeanCustomizers) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); + this.typeHandlers = typeHandlersProvider.getIfAvailable(); + this.languageDrivers = languageDriversProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); + this.sqlSessionFactoryBeanCustomizers = sqlSessionFactoryBeanCustomizers.getIfAvailable(); } @Override @@ -117,8 +132,8 @@ public void afterPropertiesSet() { private void checkConfigFileExists() { if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) { Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation()); - Assert.state(resource.exists(), "Cannot find config location: " + resource - + " (please add config file or check your Mybatis configuration)"); + Assert.state(resource.exists(), + "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)"); } } @@ -127,7 +142,9 @@ private void checkConfigFileExists() { public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); - factory.setVfs(SpringBootVFS.class); + if (properties.getConfiguration() == null || properties.getConfiguration().getVfsImpl() == null) { + factory.setVfs(SpringBootVFS.class); + } if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } @@ -150,18 +167,41 @@ public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Excepti if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } - if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { - factory.setMapperLocations(this.properties.resolveMapperLocations()); + if (!ObjectUtils.isEmpty(this.typeHandlers)) { + factory.setTypeHandlers(this.typeHandlers); } - + Resource[] mapperLocations = this.properties.resolveMapperLocations(); + if (!ObjectUtils.isEmpty(mapperLocations)) { + factory.setMapperLocations(mapperLocations); + } + Set factoryPropertyNames = Stream + .of(new BeanWrapperImpl(SqlSessionFactoryBean.class).getPropertyDescriptors()).map(PropertyDescriptor::getName) + .collect(Collectors.toSet()); + Class defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); + if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) { + // Need to mybatis-spring 2.0.2+ + factory.setScriptingLanguageDrivers(this.languageDrivers); + if (defaultLanguageDriver == null && this.languageDrivers.length == 1) { + defaultLanguageDriver = this.languageDrivers[0].getClass(); + } + } + if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) { + // Need to mybatis-spring 2.0.2+ + factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver); + } + applySqlSessionFactoryBeanCustomizers(factory); return factory.getObject(); } private void applyConfiguration(SqlSessionFactoryBean factory) { - Configuration configuration = this.properties.getConfiguration(); - if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) { + MybatisProperties.CoreConfiguration coreConfiguration = this.properties.getConfiguration(); + Configuration configuration = null; + if (coreConfiguration != null || !StringUtils.hasText(this.properties.getConfigLocation())) { configuration = new Configuration(); } + if (configuration != null && coreConfiguration != null) { + coreConfiguration.applyTo(configuration); + } if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { for (ConfigurationCustomizer customizer : this.configurationCustomizers) { customizer.customize(configuration); @@ -170,6 +210,14 @@ private void applyConfiguration(SqlSessionFactoryBean factory) { factory.setConfiguration(configuration); } + private void applySqlSessionFactoryBeanCustomizers(SqlSessionFactoryBean factory) { + if (!CollectionUtils.isEmpty(this.sqlSessionFactoryBeanCustomizers)) { + for (SqlSessionFactoryBeanCustomizer customizer : this.sqlSessionFactoryBeanCustomizers) { + customizer.customize(factory); + } + } + } + @Bean @ConditionalOnMissingBean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { @@ -182,91 +230,107 @@ public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory } /** - * This will just scan the same base package as Spring Boot does. If you want - * more power, you can explicitly use - * {@link org.mybatis.spring.annotation.MapperScan} but this will get typed - * mappers working correctly, out-of-the-box, similar to using Spring Data JPA - * repositories. + * This will just scan the same base package as Spring Boot does. If you want more power, you can explicitly use + * {@link tk.mybatis.spring.annotation.MapperScan} but this will get typed mappers working correctly, out-of-the-box, + * similar to using Spring Data JPA repositories. */ public static class AutoConfiguredMapperScannerRegistrar - implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { + implements BeanFactoryAware, ResourceLoaderAware, EnvironmentAware, ImportBeanDefinitionRegistrar { private BeanFactory beanFactory; - private ResourceLoader resourceLoader; - private Environment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + if (!AutoConfigurationPackages.has(this.beanFactory)) { + logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled."); + return; + } + logger.debug("Searching for mappers annotated with @Mapper"); - ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry, environment); - scanner.setMapperProperties(environment); - try { - if (this.resourceLoader != null) { - scanner.setResourceLoader(this.resourceLoader); - } - List packages = AutoConfigurationPackages.get(this.beanFactory); - if (logger.isDebugEnabled()) { - for (String pkg : packages) { - logger.debug("Using auto-configuration base package '{}'", pkg); - } - } - BaseProperties properties = SpringBootBindUtil.bind(environment, BaseProperties.class, BaseProperties.MYBATIS_PREFIX); - if (properties != null && properties.getBasePackages() != null && properties.getBasePackages().length > 0) { - packages.addAll(Arrays.asList(properties.getBasePackages())); - } else { - //设置了包名的情况下,不需要指定该注解 - scanner.setAnnotationClass(Mapper.class); - } + List packages = AutoConfigurationPackages.get(this.beanFactory); + if (logger.isDebugEnabled()) { + packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg)); + } - String lazyInitialization = environment.getProperty("mybatis.lazy-initialization"); - if (StringUtils.hasText(lazyInitialization)) { - scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); - } + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); + builder.addPropertyValue("processPropertyPlaceHolders", true); + builder.addPropertyValue("annotationClass", Mapper.class); + builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); + builder.addPropertyValue("mapperProperties", this.environment); + BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class); + Set propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName) + .collect(Collectors.toSet()); + if (propertyNames.contains("lazyInitialization")) { + // Need to mybatis-spring 2.0.2+ + builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}"); + } + if (propertyNames.contains("defaultScope")) { + // Need to mybatis-spring 2.0.6+ + builder.addPropertyValue("defaultScope", "${mybatis.mapper-default-scope:}"); + } - scanner.registerFilters(); - scanner.doScan(StringUtils.toStringArray(packages)); - } catch (IllegalStateException ex) { - logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex); + // for spring-native + boolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class, + Boolean.TRUE); + if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) { + ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory; + Optional sqlSessionTemplateBeanName = Optional + .ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory)); + Optional sqlSessionFactoryBeanName = Optional + .ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory)); + if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) { + builder.addPropertyValue("sqlSessionTemplateBeanName", + sqlSessionTemplateBeanName.orElse("sqlSessionTemplate")); + } else { + builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get()); + } } + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + + registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition()); } @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + @Override public void setEnvironment(Environment environment) { this.environment = environment; } - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; + private String getBeanNameForType(Class type, ListableBeanFactory factory) { + String[] beanNames = factory.getBeanNamesForType(type); + return beanNames.length > 0 ? beanNames[0] : null; } + } /** - * {@link org.mybatis.spring.annotation.MapperScan} ultimately ends up - * creating instances of {@link MapperFactoryBean}. If - * {@link org.mybatis.spring.annotation.MapperScan} is used then this - * auto-configuration is not needed. If it is _not_ used, however, then this - * will bring in a bean registrar and automatically register components based - * on the same component-scanning path as Spring Boot itself. + * If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan + * mappers based on the same component-scanning path as Spring Boot itself. */ - @org.springframework.context.annotation.Configuration - @Import({AutoConfiguredMapperScannerRegistrar.class}) - @ConditionalOnMissingBean(MapperFactoryBean.class) + @org.springframework.context.annotation.Configuration(proxyBeanMethods = false) + @Import(AutoConfiguredMapperScannerRegistrar.class) + @ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class}) public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean { @Override public void afterPropertiesSet() { - logger.debug("No {} found.", MapperFactoryBean.class.getName()); + logger.debug( + "Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer."); } + } /** @@ -282,4 +346,5 @@ public MapperCacheDisabler mapperCacheDisabler() { } } + } diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisDependsOnDatabaseInitializationDetector.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisDependsOnDatabaseInitializationDetector.java new file mode 100644 index 000000000..26fa98b6d --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisDependsOnDatabaseInitializationDetector.java @@ -0,0 +1,24 @@ +package tk.mybatis.mapper.autoconfigure; + +import java.util.Collections; +import java.util.Set; + +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDependsOnDatabaseInitializationDetector; +import org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector; + +/** + * {@link DependsOnDatabaseInitializationDetector} for Mybatis. + * + * @author Eddú Meléndez + * @since 2.3.0 + */ +class MybatisDependsOnDatabaseInitializationDetector + extends AbstractBeansOfTypeDependsOnDatabaseInitializationDetector { + + @Override + protected Set> getDependsOnDatabaseInitializationBeanTypes() { + return Collections.singleton(SqlSessionTemplate.class); + } + +} diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisLanguageDriverAutoConfiguration.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisLanguageDriverAutoConfiguration.java new file mode 100644 index 000000000..85c2a245c --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisLanguageDriverAutoConfiguration.java @@ -0,0 +1,136 @@ +package tk.mybatis.mapper.autoconfigure; + +import org.apache.ibatis.scripting.LanguageDriver; +import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver; +import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig; +import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver; +import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig; +import org.mybatis.scripting.velocity.VelocityLanguageDriver; +import org.mybatis.scripting.velocity.VelocityLanguageDriverConfig; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * {@link EnableAutoConfiguration Auto-Configuration} for MyBatis's scripting language drivers. + * + * @author Kazuki Shimizu + * @since 2.1.0 + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(LanguageDriver.class) +public class MybatisLanguageDriverAutoConfiguration { + + private static final String CONFIGURATION_PROPERTY_PREFIX = "mybatis.scripting-language-driver"; + + /** + * Configuration class for mybatis-freemarker 1.1.x or under. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(FreeMarkerLanguageDriver.class) + @ConditionalOnMissingClass("org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig") + public static class LegacyFreeMarkerConfiguration { + @Bean + @ConditionalOnMissingBean + FreeMarkerLanguageDriver freeMarkerLanguageDriver() { + return new FreeMarkerLanguageDriver(); + } + } + + /** + * Configuration class for mybatis-freemarker 1.2.x or above. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({FreeMarkerLanguageDriver.class, FreeMarkerLanguageDriverConfig.class}) + public static class FreeMarkerConfiguration { + @Bean + @ConditionalOnMissingBean + FreeMarkerLanguageDriver freeMarkerLanguageDriver(FreeMarkerLanguageDriverConfig config) { + return new FreeMarkerLanguageDriver(config); + } + + @Bean + @ConditionalOnMissingBean + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".freemarker") + public FreeMarkerLanguageDriverConfig freeMarkerLanguageDriverConfig() { + return FreeMarkerLanguageDriverConfig.newInstance(); + } + } + + /** + * Configuration class for mybatis-velocity 2.0 or under. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(org.mybatis.scripting.velocity.Driver.class) + @ConditionalOnMissingClass("org.mybatis.scripting.velocity.VelocityLanguageDriverConfig") + @SuppressWarnings("deprecation") + public static class LegacyVelocityConfiguration { + @Bean + @ConditionalOnMissingBean + org.mybatis.scripting.velocity.Driver velocityLanguageDriver() { + return new org.mybatis.scripting.velocity.Driver(); + } + } + + /** + * Configuration class for mybatis-velocity 2.1.x or above. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({VelocityLanguageDriver.class, VelocityLanguageDriverConfig.class}) + public static class VelocityConfiguration { + @Bean + @ConditionalOnMissingBean + VelocityLanguageDriver velocityLanguageDriver(VelocityLanguageDriverConfig config) { + return new VelocityLanguageDriver(config); + } + + @Bean + @ConditionalOnMissingBean + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".velocity") + public VelocityLanguageDriverConfig velocityLanguageDriverConfig() { + return VelocityLanguageDriverConfig.newInstance(); + } + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(ThymeleafLanguageDriver.class) + public static class ThymeleafConfiguration { + @Bean + @ConditionalOnMissingBean + ThymeleafLanguageDriver thymeleafLanguageDriver(ThymeleafLanguageDriverConfig config) { + return new ThymeleafLanguageDriver(config); + } + + @Bean + @ConditionalOnMissingBean + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf") + public ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() { + return ThymeleafLanguageDriverConfig.newInstance(); + } + + // This class provides to avoid the https://github.com/spring-projects/spring-boot/issues/21626 as workaround. + @SuppressWarnings("unused") + private static class MetadataThymeleafLanguageDriverConfig extends ThymeleafLanguageDriverConfig { + + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf.dialect") + @Override + public DialectConfig getDialect() { + return super.getDialect(); + } + + @ConfigurationProperties(CONFIGURATION_PROPERTY_PREFIX + ".thymeleaf.template-file") + @Override + public TemplateFileConfig getTemplateFile() { + return super.getTemplateFile(); + } + + } + + } + +} + diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisProperties.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisProperties.java index 33130ffa6..fd6af07fa 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisProperties.java +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MybatisProperties.java @@ -15,20 +15,29 @@ */ package tk.mybatis.mapper.autoconfigure; +import org.apache.ibatis.io.VFS; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.mapping.ResultSetType; +import org.apache.ibatis.scripting.LanguageDriver; +import org.apache.ibatis.session.AutoMappingBehavior; +import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.LocalCacheScope; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import tk.mybatis.spring.annotation.BaseProperties; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.Optional; import java.util.Properties; +import java.util.Set; +import java.util.stream.Stream; /** * Configuration properties for MyBatis. @@ -57,8 +66,8 @@ public class MybatisProperties extends BaseProperties { private String typeAliasesPackage; /** - * The super class for filtering type alias. - * If this not specifies, the MyBatis deal as type alias all classes that searched from typeAliasesPackage. + * The super class for filtering type alias. If this not specifies, the MyBatis deal as type alias all classes that + * searched from typeAliasesPackage. */ private Class typeAliasesSuperType; @@ -77,17 +86,21 @@ public class MybatisProperties extends BaseProperties { */ private ExecutorType executorType; + /** + * The default scripting language driver class. (Available when use together with mybatis-spring 2.0.2+) + */ + private Class defaultScriptingLanguageDriver; + /** * Externalized properties for MyBatis configuration. */ private Properties configurationProperties; /** - * A Configuration object for customize default settings. If {@link #configLocation} - * is specified, this property is not used. + * A Configuration object for customize default settings. If {@link #configLocation} is specified, this property is + * not used. */ - @NestedConfigurationProperty - private Configuration configuration; + private CoreConfiguration configuration; /** * @since 1.1.0 @@ -103,16 +116,6 @@ public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } - @Deprecated - public String getConfig() { - return this.configLocation; - } - - @Deprecated - public void setConfig(String config) { - this.configLocation = config; - } - public String[] getMapperLocations() { return this.mapperLocations; } @@ -167,6 +170,20 @@ public void setExecutorType(ExecutorType executorType) { this.executorType = executorType; } + /** + * @since 2.1.0 + */ + public Class getDefaultScriptingLanguageDriver() { + return defaultScriptingLanguageDriver; + } + + /** + * @since 2.1.0 + */ + public void setDefaultScriptingLanguageDriver(Class defaultScriptingLanguageDriver) { + this.defaultScriptingLanguageDriver = defaultScriptingLanguageDriver; + } + /** * @since 1.2.0 */ @@ -181,22 +198,17 @@ public void setConfigurationProperties(Properties configurationProperties) { this.configurationProperties = configurationProperties; } - public Configuration getConfiguration() { + public CoreConfiguration getConfiguration() { return configuration; } - public void setConfiguration(Configuration configuration) { + public void setConfiguration(CoreConfiguration configuration) { this.configuration = configuration; } public Resource[] resolveMapperLocations() { - List resources = new ArrayList(); - if (this.mapperLocations != null) { - for (String mapperLocation : this.mapperLocations) { - resources.addAll(Arrays.asList(getResources(mapperLocation))); - } - } - return resources.toArray(new Resource[resources.size()]); + return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0])) + .flatMap(location -> Stream.of(getResources(location))).toArray(Resource[]::new); } private Resource[] getResources(String location) { @@ -207,4 +219,463 @@ private Resource[] getResources(String location) { } } + /** + * The configuration properties for mybatis core module. + * + * @since 3.0.0 + */ + public static class CoreConfiguration { + + /** + * Specifies the TypeHandler used by default for Enum. + */ + Class defaultEnumTypeHandler; + /** + * Allows using RowBounds on nested statements. If allow, set the false. Default is false. + */ + private Boolean safeRowBoundsEnabled; + /** + * Allows using ResultHandler on nested statements. If allow, set the false. Default is true. + */ + private Boolean safeResultHandlerEnabled; + /** + * Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names + * aColumn. Default is false. + */ + private Boolean mapUnderscoreToCamelCase; + /** + * When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded + * on demand (see also lazyLoadTriggerMethods). Default is false. + */ + private Boolean aggressiveLazyLoading; + /** + * Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required). + * Default is true. + */ + private Boolean multipleResultSetsEnabled; + /** + * Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be + * used if set to true, as some drivers deny compatibility but still work (e.g. Derby). Default is false. + */ + private Boolean useGeneratedKeys; + /** + * Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to + * the driver documentation, or test out both modes to determine how your driver behaves. Default is true. + */ + private Boolean useColumnLabel; + /** + * Globally enables or disables any caches configured in any mapper under this configuration. Default is true. + */ + private Boolean cacheEnabled; + /** + * Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you + * rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to + * null. Default is false. + */ + private Boolean callSettersOnNulls; + /** + * Allow referencing statement parameters by their actual names declared in the method signature. To use this + * feature, your project must be compiled in Java 8 with -parameters option. Default is true. + */ + private Boolean useActualParamName; + /** + * MyBatis, by default, returns null when all the columns of a returned row are NULL. When this setting is enabled, + * MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collectioin and + * association). Default is false. + */ + private Boolean returnInstanceForEmptyRow; + /** + * Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. Default is + * false. + */ + private Boolean shrinkWhitespacesInSql; + /** + * Specifies the default value of 'nullable' attribute on 'foreach' tag. Default is false. + */ + private Boolean nullableOnForEach; + /** + * When applying constructor auto-mapping, argument name is used to search the column to map instead of relying on + * the column order. Default is false. + */ + private Boolean argNameBasedConstructorAutoMapping; + /** + * Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be + * superseded for a specific relation by using the fetchType attribute on it. Default is False. + */ + private Boolean lazyLoadingEnabled; + /** + * Sets the number of seconds the driver will wait for a response from the database. + */ + private Integer defaultStatementTimeout; + /** + * Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a + * query setting. + */ + private Integer defaultFetchSize; + /** + * MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default + * (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be + * used just for statement execution, no data will be shared between two different calls to the same SqlSession. + * Default is SESSION. + */ + private LocalCacheScope localCacheScope; + /** + * Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers + * require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. Default + * is OTHER. + */ + private JdbcType jdbcTypeForNull; + /** + * Specifies a scroll strategy when omit it per statement settings. + */ + private ResultSetType defaultResultSetType; + /** + * Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements. + * BATCH executor reuses statements and batches updates. Default is SIMPLE. + */ + private ExecutorType defaultExecutorType; + /** + * Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping. + * PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result + * mappings of any complexity (containing nested or otherwise). Default is PARTIAL. + */ + private AutoMappingBehavior autoMappingBehavior; + /** + * Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target. + * Default is NONE. + */ + private AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior; + /** + * Specifies the prefix string that MyBatis will add to the logger names. + */ + private String logPrefix; + /** + * Specifies which Object's methods trigger a lazy load. Default is [equals,clone,hashCode,toString]. + */ + private Set lazyLoadTriggerMethods; + /** + * Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation + * will be autodiscovered. + */ + private Class logImpl; + /** + * Specifies VFS implementations. + */ + private Class vfsImpl; + /** + * Specifies an sql provider class that holds provider method. This class apply to the type(or value) attribute on + * sql provider annotation(e.g. @SelectProvider), when these attribute was omitted. + */ + private Class defaultSqlProviderType; + /** + * Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to + * load lazy properties of deserialized objects. This class must have a method with a signature static Configuration + * getConfiguration(). + */ + private Class configurationFactory; + + /** + * Specify any configuration variables. + */ + private Properties variables; + + /** + * Specifies the database identify value for switching query to use. + */ + private String databaseId; + + public Boolean getSafeRowBoundsEnabled() { + return safeRowBoundsEnabled; + } + + public void setSafeRowBoundsEnabled(Boolean safeRowBoundsEnabled) { + this.safeRowBoundsEnabled = safeRowBoundsEnabled; + } + + public Boolean getSafeResultHandlerEnabled() { + return safeResultHandlerEnabled; + } + + public void setSafeResultHandlerEnabled(Boolean safeResultHandlerEnabled) { + this.safeResultHandlerEnabled = safeResultHandlerEnabled; + } + + public Boolean getMapUnderscoreToCamelCase() { + return mapUnderscoreToCamelCase; + } + + public void setMapUnderscoreToCamelCase(Boolean mapUnderscoreToCamelCase) { + this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase; + } + + public Boolean getAggressiveLazyLoading() { + return aggressiveLazyLoading; + } + + public void setAggressiveLazyLoading(Boolean aggressiveLazyLoading) { + this.aggressiveLazyLoading = aggressiveLazyLoading; + } + + public Boolean getMultipleResultSetsEnabled() { + return multipleResultSetsEnabled; + } + + public void setMultipleResultSetsEnabled(Boolean multipleResultSetsEnabled) { + this.multipleResultSetsEnabled = multipleResultSetsEnabled; + } + + public Boolean getUseGeneratedKeys() { + return useGeneratedKeys; + } + + public void setUseGeneratedKeys(Boolean useGeneratedKeys) { + this.useGeneratedKeys = useGeneratedKeys; + } + + public Boolean getUseColumnLabel() { + return useColumnLabel; + } + + public void setUseColumnLabel(Boolean useColumnLabel) { + this.useColumnLabel = useColumnLabel; + } + + public Boolean getCacheEnabled() { + return cacheEnabled; + } + + public void setCacheEnabled(Boolean cacheEnabled) { + this.cacheEnabled = cacheEnabled; + } + + public Boolean getCallSettersOnNulls() { + return callSettersOnNulls; + } + + public void setCallSettersOnNulls(Boolean callSettersOnNulls) { + this.callSettersOnNulls = callSettersOnNulls; + } + + public Boolean getUseActualParamName() { + return useActualParamName; + } + + public void setUseActualParamName(Boolean useActualParamName) { + this.useActualParamName = useActualParamName; + } + + public Boolean getReturnInstanceForEmptyRow() { + return returnInstanceForEmptyRow; + } + + public void setReturnInstanceForEmptyRow(Boolean returnInstanceForEmptyRow) { + this.returnInstanceForEmptyRow = returnInstanceForEmptyRow; + } + + public Boolean getShrinkWhitespacesInSql() { + return shrinkWhitespacesInSql; + } + + public void setShrinkWhitespacesInSql(Boolean shrinkWhitespacesInSql) { + this.shrinkWhitespacesInSql = shrinkWhitespacesInSql; + } + + public Boolean getNullableOnForEach() { + return nullableOnForEach; + } + + public void setNullableOnForEach(Boolean nullableOnForEach) { + this.nullableOnForEach = nullableOnForEach; + } + + public Boolean getArgNameBasedConstructorAutoMapping() { + return argNameBasedConstructorAutoMapping; + } + + public void setArgNameBasedConstructorAutoMapping(Boolean argNameBasedConstructorAutoMapping) { + this.argNameBasedConstructorAutoMapping = argNameBasedConstructorAutoMapping; + } + + public String getLogPrefix() { + return logPrefix; + } + + public void setLogPrefix(String logPrefix) { + this.logPrefix = logPrefix; + } + + public Class getLogImpl() { + return logImpl; + } + + public void setLogImpl(Class logImpl) { + this.logImpl = logImpl; + } + + public Class getVfsImpl() { + return vfsImpl; + } + + public void setVfsImpl(Class vfsImpl) { + this.vfsImpl = vfsImpl; + } + + public Class getDefaultSqlProviderType() { + return defaultSqlProviderType; + } + + public void setDefaultSqlProviderType(Class defaultSqlProviderType) { + this.defaultSqlProviderType = defaultSqlProviderType; + } + + public LocalCacheScope getLocalCacheScope() { + return localCacheScope; + } + + public void setLocalCacheScope(LocalCacheScope localCacheScope) { + this.localCacheScope = localCacheScope; + } + + public JdbcType getJdbcTypeForNull() { + return jdbcTypeForNull; + } + + public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) { + this.jdbcTypeForNull = jdbcTypeForNull; + } + + public Set getLazyLoadTriggerMethods() { + return lazyLoadTriggerMethods; + } + + public void setLazyLoadTriggerMethods(Set lazyLoadTriggerMethods) { + this.lazyLoadTriggerMethods = lazyLoadTriggerMethods; + } + + public Integer getDefaultStatementTimeout() { + return defaultStatementTimeout; + } + + public void setDefaultStatementTimeout(Integer defaultStatementTimeout) { + this.defaultStatementTimeout = defaultStatementTimeout; + } + + public Integer getDefaultFetchSize() { + return defaultFetchSize; + } + + public void setDefaultFetchSize(Integer defaultFetchSize) { + this.defaultFetchSize = defaultFetchSize; + } + + public ResultSetType getDefaultResultSetType() { + return defaultResultSetType; + } + + public void setDefaultResultSetType(ResultSetType defaultResultSetType) { + this.defaultResultSetType = defaultResultSetType; + } + + public ExecutorType getDefaultExecutorType() { + return defaultExecutorType; + } + + public void setDefaultExecutorType(ExecutorType defaultExecutorType) { + this.defaultExecutorType = defaultExecutorType; + } + + public AutoMappingBehavior getAutoMappingBehavior() { + return autoMappingBehavior; + } + + public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) { + this.autoMappingBehavior = autoMappingBehavior; + } + + public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() { + return autoMappingUnknownColumnBehavior; + } + + public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) { + this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior; + } + + public Properties getVariables() { + return variables; + } + + public void setVariables(Properties variables) { + this.variables = variables; + } + + public Boolean getLazyLoadingEnabled() { + return lazyLoadingEnabled; + } + + public void setLazyLoadingEnabled(Boolean lazyLoadingEnabled) { + this.lazyLoadingEnabled = lazyLoadingEnabled; + } + + public Class getConfigurationFactory() { + return configurationFactory; + } + + public void setConfigurationFactory(Class configurationFactory) { + this.configurationFactory = configurationFactory; + } + + public Class getDefaultEnumTypeHandler() { + return defaultEnumTypeHandler; + } + + public void setDefaultEnumTypeHandler(Class defaultEnumTypeHandler) { + this.defaultEnumTypeHandler = defaultEnumTypeHandler; + } + + public String getDatabaseId() { + return databaseId; + } + + public void setDatabaseId(String databaseId) { + this.databaseId = databaseId; + } + + public void applyTo(Configuration target) { + PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); + mapper.from(getSafeRowBoundsEnabled()).to(target::setSafeRowBoundsEnabled); + mapper.from(getSafeResultHandlerEnabled()).to(target::setSafeResultHandlerEnabled); + mapper.from(getMapUnderscoreToCamelCase()).to(target::setMapUnderscoreToCamelCase); + mapper.from(getAggressiveLazyLoading()).to(target::setAggressiveLazyLoading); + mapper.from(getMultipleResultSetsEnabled()).to(target::setMultipleResultSetsEnabled); + mapper.from(getUseGeneratedKeys()).to(target::setUseGeneratedKeys); + mapper.from(getUseColumnLabel()).to(target::setUseColumnLabel); + mapper.from(getCacheEnabled()).to(target::setCacheEnabled); + mapper.from(getCallSettersOnNulls()).to(target::setCallSettersOnNulls); + mapper.from(getUseActualParamName()).to(target::setUseActualParamName); + mapper.from(getReturnInstanceForEmptyRow()).to(target::setReturnInstanceForEmptyRow); + mapper.from(getShrinkWhitespacesInSql()).to(target::setShrinkWhitespacesInSql); + mapper.from(getNullableOnForEach()).to(target::setNullableOnForEach); + mapper.from(getArgNameBasedConstructorAutoMapping()).to(target::setArgNameBasedConstructorAutoMapping); + mapper.from(getLazyLoadingEnabled()).to(target::setLazyLoadingEnabled); + mapper.from(getLogPrefix()).to(target::setLogPrefix); + mapper.from(getLazyLoadTriggerMethods()).to(target::setLazyLoadTriggerMethods); + mapper.from(getDefaultStatementTimeout()).to(target::setDefaultStatementTimeout); + mapper.from(getDefaultFetchSize()).to(target::setDefaultFetchSize); + mapper.from(getLocalCacheScope()).to(target::setLocalCacheScope); + mapper.from(getJdbcTypeForNull()).to(target::setJdbcTypeForNull); + mapper.from(getDefaultResultSetType()).to(target::setDefaultResultSetType); + mapper.from(getDefaultExecutorType()).to(target::setDefaultExecutorType); + mapper.from(getAutoMappingBehavior()).to(target::setAutoMappingBehavior); + mapper.from(getAutoMappingUnknownColumnBehavior()).to(target::setAutoMappingUnknownColumnBehavior); + mapper.from(getVariables()).to(target::setVariables); + mapper.from(getLogImpl()).to(target::setLogImpl); + mapper.from(getVfsImpl()).to(target::setVfsImpl); + mapper.from(getDefaultSqlProviderType()).to(target::setDefaultSqlProviderType); + mapper.from(getConfigurationFactory()).to(target::setConfigurationFactory); + mapper.from(getDefaultEnumTypeHandler()).to(target::setDefaultEnumTypeHandler); + mapper.from(getDatabaseId()).to(target::setDatabaseId); + } + + } + } diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SpringBootVFS.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SpringBootVFS.java index 66d0b77b0..e68354615 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SpringBootVFS.java +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SpringBootVFS.java @@ -15,16 +15,22 @@ */ package tk.mybatis.mapper.autoconfigure; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.text.Normalizer; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.apache.ibatis.io.VFS; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; - -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; +import org.springframework.util.ClassUtils; /** * @author Hans Westerbeek @@ -33,10 +39,17 @@ */ public class SpringBootVFS extends VFS { + private static Charset urlDecodingCharset; + private static Supplier classLoaderSupplier; private final ResourcePatternResolver resourceResolver; + static { + setUrlDecodingCharset(Charset.defaultCharset()); + setClassLoaderSupplier(ClassUtils::getDefaultClassLoader); + } + public SpringBootVFS() { - this.resourceResolver = new PathMatchingResourcePatternResolver(getClass().getClassLoader()); + this.resourceResolver = new PathMatchingResourcePatternResolver(classLoaderSupplier.get()); } @Override @@ -44,20 +57,51 @@ public boolean isValid() { return true; } - @Override - protected List list(URL url, String path) throws IOException { - Resource[] resources = resourceResolver.getResources("classpath*:" + path + "/**/*.class"); - List resourcePaths = new ArrayList(); - for (Resource resource : resources) { - resourcePaths.add(preserveSubpackageName(resource.getURI(), path)); + /** + * Set the charset for decoding an encoded URL string. + *

+ * Default is system default charset. + *

+ * + * @param charset the charset for decoding an encoded URL string + * @since 2.3.0 + */ + public static void setUrlDecodingCharset(Charset charset) { + urlDecodingCharset = charset; + } + + /** + * Set the supplier for providing {@link ClassLoader} to used. + *

+ * Default is a returned instance from {@link ClassUtils#getDefaultClassLoader()}. + *

+ * + * @param supplier the supplier for providing {@link ClassLoader} to used + * @since 3.0.2 + */ + public static void setClassLoaderSupplier(Supplier supplier) { + classLoaderSupplier = supplier; + } + + private static String preserveSubpackageName(final String baseUrlString, final Resource resource, + final String rootPath) { + try { + return rootPath + (rootPath.endsWith("/") ? "" : "/") + + Normalizer + .normalize(URLDecoder.decode(resource.getURL().toString(), urlDecodingCharset), Normalizer.Form.NFC) + .substring(baseUrlString.length()); + } catch (IOException e) { + throw new UncheckedIOException(e); } - return resourcePaths; } - private static String preserveSubpackageName(final URI uri, final String rootPath) { - final String uriStr = uri.toString(); - final int start = uriStr.indexOf(rootPath); - return uriStr.substring(start); + @Override + protected List list(URL url, String path) throws IOException { + String urlString = URLDecoder.decode(url.toString(), urlDecodingCharset); + String baseUrlString = urlString.endsWith("/") ? urlString : urlString.concat("/"); + Resource[] resources = resourceResolver.getResources(baseUrlString + "**/*.class"); + return Stream.of(resources).map(resource -> preserveSubpackageName(baseUrlString, resource, path)) + .collect(Collectors.toList()); } } diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SqlSessionFactoryBeanCustomizer.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SqlSessionFactoryBeanCustomizer.java new file mode 100644 index 000000000..2a3111460 --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/SqlSessionFactoryBeanCustomizer.java @@ -0,0 +1,21 @@ +package tk.mybatis.mapper.autoconfigure; + +import org.mybatis.spring.SqlSessionFactoryBean; + +/** + * Callback interface that can be customized a {@link SqlSessionFactoryBean} object generated on auto-configuration. + * + * @author Kazuki Shimizu + * @since 2.2.2 + */ +@FunctionalInterface +public interface SqlSessionFactoryBeanCustomizer { + + /** + * Customize the given a {@link SqlSessionFactoryBean} object. + * + * @param factoryBean the factory bean object to customize + */ + void customize(SqlSessionFactoryBean factoryBean); + +} diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 48243cbf6..e62a7c18c 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ +tk.mybatis.mapper.autoconfigure.MybatisLanguageDriverAutoConfiguration tk.mybatis.mapper.autoconfigure.MapperAutoConfiguration \ No newline at end of file diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties index dca3cf5cf..5613106ea 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/application.properties @@ -23,4 +23,8 @@ # spring.sql.init.schema-locations=classpath:import.sql logging.level.root=WARN -logging.level.tk.mybatis.sample.mapper=TRACE \ No newline at end of file +logging.level.tk.mybatis.sample.mapper=TRACE +mapper.useSimpleType=false +mapper.enable-method-annotation=true +mapper.style=uppercase +mybatis.configuration.logImpl=org.apache.ibatis.logging.slf4j.Slf4jImpl \ No newline at end of file diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/logback.xml b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/logback.xml new file mode 100644 index 000000000..cbc7d3ef0 --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-annotation/src/main/resources/logback.xml @@ -0,0 +1,10 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + \ No newline at end of file diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java index 57fdf5de2..1592b777b 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/java/tk/mybatis/sample/SampleXmlApplication.java @@ -24,12 +24,14 @@ package tk.mybatis.sample; +import org.apache.ibatis.annotations.Mapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.sample.domain.Country; import tk.mybatis.sample.mapper.CountryMapper; +import tk.mybatis.spring.annotation.MapperScan; import java.util.List; diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml index 31048949b..aac52a11e 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml @@ -28,6 +28,8 @@ spring: mybatis: config-location: mybatis-config.xml base-packages: tk.mybatis.sample.mapper + mapper-locations: + - classpath: /tk/mybatis/sample/mapper logging: level: diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/logback.xml b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/logback.xml new file mode 100644 index 000000000..cbc7d3ef0 --- /dev/null +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/logback.xml @@ -0,0 +1,10 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + \ No newline at end of file diff --git a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java index b4b3bac80..1528e3b9d 100644 --- a/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java +++ b/spring/src/main/java/tk/mybatis/spring/annotation/MapperScans.java @@ -20,17 +20,17 @@ import java.lang.annotation.*; /** - * The Container annotation that aggregates several {@link org.mybatis.spring.annotation.MapperScan} annotations. + * The Container annotation that aggregates several {@link tk.mybatis.spring.annotation.MapperScan} annotations. *

- * Can be used natively, declaring several nested {@link org.mybatis.spring.annotation.MapperScan} annotations. Can also be used in conjunction with - * Java 8's support for repeatable annotations, where {@link org.mybatis.spring.annotation.MapperScan} can simply be declared several times on the + * Can be used natively, declaring several nested {@link tk.mybatis.spring.annotation.MapperScan} annotations. Can also be used in conjunction with + * Java 8's support for repeatable annotations, where {@link tk.mybatis.spring.annotation.MapperScan} can simply be declared several times on the * same method, implicitly generating this container annotation. * * @author Kazuki Shimizu * * @since 2.0.0 * - * @see org.mybatis.spring.annotation.MapperScan + * @see tk.mybatis.spring.annotation.MapperScan */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) From 0b50897e48e988358024d2bd8910d264acbd5cc4 Mon Sep 17 00:00:00 2001 From: liuzh Date: Tue, 20 Aug 2024 22:16:33 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E5=AE=8C=E5=96=84=20mybatis.basePackages?= =?UTF-8?q?=20=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=8C=87=E5=AE=9A=E8=AF=A5?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=97=B6=E4=B8=8D=E6=8C=87=E5=AE=9A=20@Mappe?= =?UTF-8?q?r=20=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MapperAutoConfiguration.java | 27 ++++++++++++++----- .../src/main/resources/application.yml | 4 +-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java index b6c587bda..f1e504b26 100644 --- a/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java +++ b/spring-boot-starter/mapper-spring-boot-autoconfigure/src/main/java/tk/mybatis/mapper/autoconfigure/MapperAutoConfiguration.java @@ -16,6 +16,7 @@ package tk.mybatis.mapper.autoconfigure; import java.beans.PropertyDescriptor; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Set; @@ -69,8 +70,10 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; +import tk.mybatis.spring.annotation.BaseProperties; import tk.mybatis.spring.mapper.MapperFactoryBean; import tk.mybatis.spring.mapper.MapperScannerConfigurer; +import tk.mybatis.spring.mapper.SpringBootBindUtil; /** * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a {@link SqlSessionFactory} and a @@ -249,17 +252,27 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B return; } - logger.debug("Searching for mappers annotated with @Mapper"); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); - List packages = AutoConfigurationPackages.get(this.beanFactory); - if (logger.isDebugEnabled()) { - packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg)); + BaseProperties properties = SpringBootBindUtil.bind(environment, BaseProperties.class, BaseProperties.MYBATIS_PREFIX); + if (properties != null && properties.getBasePackages() != null && properties.getBasePackages().length > 0) { + List basePackages = Arrays.asList(properties.getBasePackages()); + if (logger.isDebugEnabled()) { + basePackages.forEach(pkg -> logger.debug("Using mybatis.basePackages configuration package '{}'", pkg)); + } + builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); + } else { + //设置了包名的情况下,不需要指定该注解 + logger.debug("Searching for mappers annotated with @Mapper"); + builder.addPropertyValue("annotationClass", Mapper.class); + List packages = AutoConfigurationPackages.get(this.beanFactory); + if (logger.isDebugEnabled()) { + packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg)); + } + builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); builder.addPropertyValue("processPropertyPlaceHolders", true); - builder.addPropertyValue("annotationClass", Mapper.class); - builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); builder.addPropertyValue("mapperProperties", this.environment); BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class); Set propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName) diff --git a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml index aac52a11e..7b689c046 100644 --- a/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml +++ b/spring-boot-starter/mapper-spring-boot-samples/mapper-spring-boot-sample-xml/src/main/resources/application.yml @@ -28,12 +28,10 @@ spring: mybatis: config-location: mybatis-config.xml base-packages: tk.mybatis.sample.mapper - mapper-locations: - - classpath: /tk/mybatis/sample/mapper logging: level: - root: WARN + root: DEBUG tk.mybatis.sample.mapper: TRACE mapper: not-empty: true From cf801a4609da4b544a9b3ff7b90b5ba289918574 Mon Sep 17 00:00:00 2001 From: liuzh Date: Tue, 20 Aug 2024 22:18:59 +0800 Subject: [PATCH 8/8] 5.0.0-rc2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index da994339a..159da1017 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ https://mybatis.io - 5.0.0-SNAPSHOT + 5.0.0-rc2 17 17 UTF-8