diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToMany.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToMany.java new file mode 100644 index 00000000..e778a2f0 --- /dev/null +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToMany.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.annotation; + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface RelationManyToMany { + + String selfField(); + + String targetField(); + + String joinTable(); + + String joinSelfColumn(); + + String joinTargetColumn(); + + String orderBy() default ""; + +} \ No newline at end of file diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToOne.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToOne.java new file mode 100644 index 00000000..afe56708 --- /dev/null +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationManyToOne.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.annotation; + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface RelationManyToOne { + + String selfField(); + + String targetField(); + +} \ No newline at end of file diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToMany.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToMany.java new file mode 100644 index 00000000..983b7f10 --- /dev/null +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToMany.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.annotation; + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface RelationOneToMany { + + String selfField(); + + String targetField(); + + String orderBy() default ""; + + int limit() default 0; + +} \ No newline at end of file diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToOne.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToOne.java new file mode 100644 index 00000000..9536ba16 --- /dev/null +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/RelationOneToOne.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.annotation; + +import java.lang.annotation.*; + +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface RelationOneToOne { + + String selfField(); + + String targetField(); + +} \ No newline at end of file diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java index 83e505ec..06f55fdf 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java @@ -426,6 +426,58 @@ public interface BaseMapper { return MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType)); } + + /** + * 根据 map 构建的条件来查询数据 + * + * @param map where 条件 + * @return entity 数据 + */ + default T selectOneWithRelationsByMap(Map map) { + if (map == null || map.isEmpty()) { + throw FlexExceptions.wrap("map can not be null or empty."); + } + return selectOneWithRelationsByQuery(QueryWrapper.create().where(map).limit(1)); + } + + + /** + * 根据 condition 来查询数据 + * + * @param condition 条件 + * @return 1 条数据 + */ + default T selectOneWithRelationsByCondition(QueryCondition condition) { + if (condition == null) { + throw FlexExceptions.wrap("condition can not be null."); + } + return selectOneWithRelationsByQuery(QueryWrapper.create().where(condition).limit(1)); + } + + + /** + * 根据 queryWrapper 构建的条件来查询 1 条数据 + * + * @param queryWrapper query 条件 + * @return entity 数据 + */ + default T selectOneWithRelationsByQuery(QueryWrapper queryWrapper) { + return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQuery(queryWrapper))); + } + + + /** + * 根据 queryWrapper 构建的条件来查询 1 条数据 + * + * @param queryWrapper query 条件 + * @param asType 接收类型 + * @return 数据内容 + */ + default R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class asType) { + return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType))); + } + + /** * 根据多个主键来查询多条数据 * @@ -552,7 +604,7 @@ public interface BaseMapper { return selectObjectListByQueryAs(queryWrapper, asType); } - if(Map.class.isAssignableFrom(asType)){ + if (Map.class.isAssignableFrom(asType)) { return (List) selectRowsByQuery(queryWrapper); } @@ -565,6 +617,14 @@ public interface BaseMapper { } + /** + * 根据 query 来构建条件查询数据列表,要求返回的数据为 asType + * + * @param queryWrapper 查询条件 + * @param asType 接收的数据类型 + * @param consumers 字段查询 + * @return 数据列表 + */ default List selectListByQueryAs(QueryWrapper queryWrapper, Class asType , Consumer>... consumers) { List list = selectListByQueryAs(queryWrapper, asType); @@ -577,6 +637,63 @@ public interface BaseMapper { } + /** + * 查询 entity 及其 relation 注解字段 + * + * @param queryWrapper 查询条件 + */ + default List selectListWithRelationsByQuery(QueryWrapper queryWrapper) { + return MapperUtil.queryRelations(this, selectListByQuery(queryWrapper)); + } + + + /** + * 查询 entity 及其 relation 注解字段 + * + * @param queryWrapper 查询条件 + * @param asType 要求返回的数据类型 + * @return 数据列表 + */ + default List selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class asType) { + if (Number.class.isAssignableFrom(asType) + || String.class == asType) { + return selectObjectListByQueryAs(queryWrapper, asType); + } + + if (Map.class.isAssignableFrom(asType)) { + return (List) selectRowsByQuery(queryWrapper); + } + + try { + MappedStatementTypes.setCurrentType(asType); + return MapperUtil.queryRelations(this, (List) selectListByQuery(queryWrapper)); + } finally { + MappedStatementTypes.clear(); + } + } + + + /** + * 查询 entity 及其 relation 注解字段 + * + * @param queryWrapper 查询条件 + * @param asType 返回的类型 + * @param consumers 字段查询 + * @return 数据列表 + */ + default List selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class asType + , Consumer>... consumers) { + List list = selectListByQueryAs(queryWrapper, asType); + if (list == null || list.isEmpty()) { + return Collections.emptyList(); + } else { + MapperUtil.queryRelations(this, list); + MapperUtil.queryFields(this, list, consumers); + return list; + } + } + + /** * 查询全部数据 * @@ -587,6 +704,16 @@ public interface BaseMapper { } + /** + * 查询全部数据,及其 relation 字段内容 + * + * @return 数据列表 + */ + default List selectAllWithRelations() { + return MapperUtil.queryRelations(this, selectListByQuery(new QueryWrapper())); + } + + /** * 根据 queryWrapper 1 条数据 * queryWrapper 执行的结果应该只有 1 列,例如 QueryWrapper.create().select(ACCOUNT.id).where... diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java index 42b20d83..d412d023 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java @@ -151,7 +151,7 @@ public class FlexConfiguration extends Configuration { Class asType = MappedStatementTypes.getCurrentType(); if (asType != null) { return MapUtil.computeIfAbsent(dynamicMappedStatementCache, id + ":" + asType.getName(), - aClass -> replaceResultMap(ms, TableInfoFactory.ofEntityClass(asType)) + clazz -> replaceResultMap(ms, TableInfoFactory.ofEntityClass(asType)) ); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToMany.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToMany.java new file mode 100644 index 00000000..0fda7a53 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToMany.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.annotation.RelationManyToMany; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.util.ClassUtil; +import com.mybatisflex.core.util.CollectionUtil; +import com.mybatisflex.core.util.MapperUtil; +import com.mybatisflex.core.util.StringUtil; + +import java.lang.reflect.Field; +import java.util.*; + +import static com.mybatisflex.core.query.QueryMethods.column; + +class ManyToMany extends Relation { + + private String joinTable; + private String joinSelfColumn; + private String joinTargetColumn; + + private String orderBy; + + public ManyToMany(RelationManyToMany annotation, Class entityClass, Field relationField) { + super(annotation.selfField(), annotation.targetField(), entityClass, relationField); + + this.joinTable = annotation.joinTable(); + this.joinSelfColumn = annotation.joinSelfColumn(); + this.joinTargetColumn = annotation.joinTargetColumn(); + + this.orderBy = annotation.orderBy(); + } + + @Override + public Class getMappingType() { + return Row.class; + } + + + @Override + public QueryWrapper toQueryWrapper(List selfEntities) { + Set selfFieldValues = getSelfFieldValues(selfEntities); + if (selfFieldValues.isEmpty()) { + return null; + } + + QueryWrapper queryWrapper = QueryWrapper.create().select() + .from(joinTable); + if (selfFieldValues.size() > 1) { + queryWrapper.where(column(joinSelfColumn).in(selfFieldValues)); + } else { + queryWrapper.where(column(joinSelfColumn).eq(selfFieldValues.iterator().next())); + } + + return queryWrapper; + } + + + @Override + public void map(List selfEntities, List mappingObjectList, BaseMapper mapper) { + List mappingRows = (List) mappingObjectList; + Set targetValues = new LinkedHashSet<>(); + for (Row row : mappingRows) { + Object targetValue = row.getIgnoreCase(joinTargetColumn); + if (targetValue != null) { + targetValues.add(targetValue); + } + } + + if (targetValues.isEmpty()) { + return; + } + + QueryWrapper queryWrapper = QueryWrapper.create().select() + .from(targetTableInfo.getTableNameWithSchema()); + if (targetValues.size() > 1) { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).in(targetValues)); + } else { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).eq(targetValues.iterator().next())); + } + + if (StringUtil.isNotBlank(orderBy)) { + queryWrapper.orderBy(orderBy); + } + + + List targetObjectList = mapper.selectListByQueryAs(queryWrapper, relationFieldWrapper.getMappingType()); + + if (CollectionUtil.isNotEmpty(targetObjectList)) { + selfEntities.forEach(selfEntity -> { + Object selfValue = selfFieldWrapper.get(selfEntity); + if (selfValue != null) { + selfValue = selfValue.toString(); + Set targetMappingValues = new HashSet<>(); + for (Row mappingRow : mappingRows) { + if (selfValue.equals(String.valueOf(mappingRow.getIgnoreCase(joinSelfColumn)))) { + Object joinValue = mappingRow.getIgnoreCase(joinTargetColumn); + if (joinValue != null) { + targetMappingValues.add(joinValue.toString()); + } + } + } + + if (!targetMappingValues.isEmpty()) { + Class wrapType = MapperUtil.getWrapType(relationFieldWrapper.getFieldType()); + Collection collection = (Collection) ClassUtil.newInstance(wrapType); + for (Object targetObject : targetObjectList) { + Object targetValue = targetFieldWrapper.get(targetObject); + if (targetValue != null && targetMappingValues.contains(targetValue.toString())) { + collection.add(targetObject); + } + } + relationFieldWrapper.set(collection, selfEntity); + } + } + }); + } + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToOne.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToOne.java new file mode 100644 index 00000000..2a872b82 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/ManyToOne.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.annotation.RelationManyToOne; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Set; + +import static com.mybatisflex.core.query.QueryMethods.column; + +class ManyToOne extends Relation { + + public ManyToOne(RelationManyToOne annotation, Class entityClass, Field relationField) { + super(annotation.selfField(), annotation.targetField(), entityClass, relationField); + } + + @Override + public QueryWrapper toQueryWrapper(List selfEntities) { + Set selfFieldValues = getSelfFieldValues(selfEntities); + if (selfFieldValues.isEmpty()) { + return null; + } + QueryWrapper queryWrapper = QueryWrapper.create().select() + .from(targetTableInfo.getTableNameWithSchema()); + if (selfFieldValues.size() > 1) { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).in(selfFieldValues)); + } else { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).eq(selfFieldValues.iterator().next())); + } + return queryWrapper; + } + + + @Override + public void map(List selfEntities, List targetObjectList, BaseMapper mapper) { + selfEntities.forEach(selfEntity -> { + Object selfValue = selfFieldWrapper.get(selfEntity); + if (selfValue != null) { + for (Object targetObject : targetObjectList) { + Object targetValue = targetFieldWrapper.get(targetObject); + if (selfValue.equals(targetValue)) { + relationFieldWrapper.set(targetObject, selfEntity); + break; + } + } + } + }); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToMany.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToMany.java new file mode 100644 index 00000000..b9b388ba --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToMany.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.annotation.RelationOneToMany; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.util.ClassUtil; +import com.mybatisflex.core.util.MapperUtil; +import com.mybatisflex.core.util.StringUtil; + +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static com.mybatisflex.core.query.QueryMethods.column; + +class OneToMany extends Relation { + + private String orderBy; + private int limit; + + + public OneToMany(RelationOneToMany annotation, Class entityClass, Field relationField) { + super(annotation.selfField(), annotation.targetField(), entityClass, relationField); + this.orderBy = annotation.orderBy(); + this.limit = annotation.limit(); + } + + @Override + public QueryWrapper toQueryWrapper(List selfEntities) { + Set selfFieldValues = getSelfFieldValues(selfEntities); + if (selfFieldValues.isEmpty()) { + return null; + } + QueryWrapper queryWrapper = QueryWrapper.create().select() + .from(targetTableInfo.getTableNameWithSchema()); + if (selfFieldValues.size() > 1) { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).in(selfFieldValues)); + } else { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).eq(selfFieldValues.iterator().next())); + } + + if (StringUtil.isNotBlank(orderBy)) { + queryWrapper.orderBy(orderBy); + } + + if (limit > 0) { + queryWrapper.limit(limit); + } + + return queryWrapper; + } + + @Override + public void map(List selfEntities, List targetObjectList, BaseMapper mapper) { + selfEntities.forEach(selfEntity -> { + Object selfValue = selfFieldWrapper.get(selfEntity); + if (selfValue != null) { + Class wrapType = MapperUtil.getWrapType(relationFieldWrapper.getFieldType()); + Collection collection = (Collection) ClassUtil.newInstance(wrapType); + for (Object targetObject : targetObjectList) { + Object targetValue = targetFieldWrapper.get(targetObject); + if (selfValue.equals(targetValue)) { + collection.add(targetObject); + } + } + relationFieldWrapper.set(collection, selfEntity); + } + }); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToOne.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToOne.java new file mode 100644 index 00000000..f919a2f1 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/OneToOne.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.annotation.RelationOneToOne; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Set; + +import static com.mybatisflex.core.query.QueryMethods.column; + +class OneToOne extends Relation { + + public OneToOne(RelationOneToOne annotation, Class entityClass, Field relationField) { + super(annotation.selfField(), annotation.targetField(), entityClass, relationField); + } + + + @Override + public QueryWrapper toQueryWrapper(List selfEntities) { + Set selfFieldValues = getSelfFieldValues(selfEntities); + if (selfFieldValues.isEmpty()) { + return null; + } + QueryWrapper queryWrapper = QueryWrapper.create().select() + .from(targetTableInfo.getTableNameWithSchema()); + if (selfFieldValues.size() > 1) { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).in(selfFieldValues)); + } else { + queryWrapper.where(column(targetTableInfo.getColumnByProperty(targetField.getName())).eq(selfFieldValues.iterator().next())); + } + return queryWrapper; + } + + + @Override + public void map(List selfEntities, List targetObjectList, BaseMapper mapper) { + selfEntities.forEach(selfEntity -> { + Object selfValue = selfFieldWrapper.get(selfEntity); + if (selfValue != null) { + for (Object targetObject : targetObjectList) { + Object targetValue = targetFieldWrapper.get(targetObject); + if (selfValue.equals(targetValue)) { + relationFieldWrapper.set(targetObject, selfEntity); + break; + } + } + } + }); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/Relation.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/Relation.java new file mode 100644 index 00000000..68be5e3b --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/Relation.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.table.TableInfo; +import com.mybatisflex.core.table.TableInfoFactory; +import com.mybatisflex.core.util.ClassUtil; +import com.mybatisflex.core.util.FieldWrapper; +import org.apache.ibatis.reflection.Reflector; +import org.apache.ibatis.reflection.TypeParameterResolver; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; + +abstract class Relation { + + protected Class selfEntityClass; + protected Field relationField; + protected FieldWrapper relationFieldWrapper; + + protected Field selfField; + protected FieldWrapper selfFieldWrapper; + + protected Field targetField; + protected Class targetEntityClass; + protected TableInfo targetTableInfo; + protected FieldWrapper targetFieldWrapper; + + public Relation(String selfField, String targetField, Class entityClass, Field relationField) { + this.selfEntityClass = entityClass; + this.relationField = relationField; + this.relationFieldWrapper = FieldWrapper.of(entityClass, relationField.getName()); + + this.selfField = ClassUtil.getFirstField(entityClass, field -> field.getName().equals(selfField)); + this.selfFieldWrapper = FieldWrapper.of(entityClass, selfField); + + + Reflector reflector = new Reflector(entityClass); + Class targetClass = reflector.getGetterType(relationField.getName()); + + if (Collection.class.isAssignableFrom(targetClass)) { + Type genericType = TypeParameterResolver.resolveFieldType(relationField, entityClass); + if (genericType instanceof ParameterizedType) { + this.targetEntityClass = (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0]; + } + } else if (targetClass.isArray()) { + this.targetEntityClass = targetClass.getComponentType(); + } else { + this.targetEntityClass = targetClass; + } + + this.targetField = ClassUtil.getFirstField(targetEntityClass, field -> field.getName().equals(targetField)); + this.targetFieldWrapper = FieldWrapper.of(targetEntityClass, targetField); + + this.targetTableInfo = TableInfoFactory.ofEntityClass(targetEntityClass); + } + + + public Class getSelfEntityClass() { + return selfEntityClass; + } + + public void setSelfEntityClass(Class selfEntityClass) { + this.selfEntityClass = selfEntityClass; + } + + public Field getRelationField() { + return relationField; + } + + public void setRelationField(Field relationField) { + this.relationField = relationField; + } + + public FieldWrapper getRelationFieldWrapper() { + return relationFieldWrapper; + } + + public void setRelationFieldWrapper(FieldWrapper relationFieldWrapper) { + this.relationFieldWrapper = relationFieldWrapper; + } + + public Field getSelfField() { + return selfField; + } + + public void setSelfField(Field selfField) { + this.selfField = selfField; + } + + public FieldWrapper getSelfFieldWrapper() { + return selfFieldWrapper; + } + + public void setSelfFieldWrapper(FieldWrapper selfFieldWrapper) { + this.selfFieldWrapper = selfFieldWrapper; + } + + public Field getTargetField() { + return targetField; + } + + public void setTargetField(Field targetField) { + this.targetField = targetField; + } + + public Class getTargetEntityClass() { + return targetEntityClass; + } + + public void setTargetEntityClass(Class targetEntityClass) { + this.targetEntityClass = targetEntityClass; + } + + public TableInfo getTargetTableInfo() { + return targetTableInfo; + } + + public void setTargetTableInfo(TableInfo targetTableInfo) { + this.targetTableInfo = targetTableInfo; + } + + public FieldWrapper getTargetFieldWrapper() { + return targetFieldWrapper; + } + + public void setTargetFieldWrapper(FieldWrapper targetFieldWrapper) { + this.targetFieldWrapper = targetFieldWrapper; + } + + protected Set getSelfFieldValues(List list) { + if (list == null || list.isEmpty()) { + return Collections.emptySet(); + } + + Set values = new LinkedHashSet<>(); + list.forEach(self -> { + Object value = selfFieldWrapper.get(self); + if (value != null && !"".equals(value)) { + values.add(value); + } + }); + return values; + } + + public abstract QueryWrapper toQueryWrapper(List selfEntities); + + public abstract void map(List selfEntities, List mappedObjectList, BaseMapper mapper); + + public Class getMappingType() { + return relationFieldWrapper.getMappingType(); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/RelationManager.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/RelationManager.java new file mode 100644 index 00000000..e043e88d --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/relation/RelationManager.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.core.relation; + +import com.mybatisflex.annotation.RelationManyToMany; +import com.mybatisflex.annotation.RelationManyToOne; +import com.mybatisflex.annotation.RelationOneToMany; +import com.mybatisflex.annotation.RelationOneToOne; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.util.ClassUtil; +import com.mybatisflex.core.util.CollectionUtil; +import org.apache.ibatis.util.MapUtil; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class RelationManager { + + private static Map, List> classRelations = new ConcurrentHashMap<>(); + + private static List getRelations(Class clazz) { + return MapUtil.computeIfAbsent(classRelations, clazz, RelationManager::doGetRelations); + } + + private static List doGetRelations(Class entityClass) { + List allFields = ClassUtil.getAllFields(entityClass); + List relations = new ArrayList<>(); + for (Field field : allFields) { + RelationManyToMany manyToManyAnnotation = field.getAnnotation(RelationManyToMany.class); + if (manyToManyAnnotation != null) { + relations.add(new ManyToMany<>(manyToManyAnnotation, entityClass, field)); + } + + RelationManyToOne manyToOneAnnotation = field.getAnnotation(RelationManyToOne.class); + if (manyToOneAnnotation != null) { + relations.add(new ManyToOne<>(manyToOneAnnotation, entityClass, field)); + } + + RelationOneToMany oneToManyAnnotation = field.getAnnotation(RelationOneToMany.class); + if (oneToManyAnnotation != null) { + relations.add(new OneToMany<>(oneToManyAnnotation, entityClass, field)); + } + + RelationOneToOne oneToOneAnnotation = field.getAnnotation(RelationOneToOne.class); + if (oneToOneAnnotation != null) { + relations.add(new OneToOne<>(oneToOneAnnotation, entityClass, field)); + } + } + return relations; + } + + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void queryRelations(BaseMapper mapper, List entities) { + if (CollectionUtil.isEmpty(entities)) { + return; + } + + Class objectClass = (Class) entities.get(0).getClass(); + List relations = getRelations(objectClass); + if (relations.isEmpty()) { + return; + } + + relations.forEach(relation -> { + QueryWrapper queryWrapper = relation.toQueryWrapper(entities); + Class mappingType = relation.getMappingType(); + + List targetObjectList = mapper.selectListByQueryAs(queryWrapper, mappingType); + if (CollectionUtil.isNotEmpty(targetObjectList)) { + relation.map(entities, targetObjectList, mapper); + } + }); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java index d809d851..bdfeee6b 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java @@ -130,6 +130,21 @@ public class Row extends LinkedHashMap implements UpdateWrapper return result != null ? result : defaultValue; } + public Object getIgnoreCase(String key){ + for (String innerKey : keySet()) { + if (innerKey.equalsIgnoreCase(key)){ + return super.get(innerKey); + } + } + return null; + } + + + public Object getIgnoreCase(String key, Object defaultValue){ + Object result = getIgnoreCase(key); + return result != null ? result : defaultValue; + } + @Override public Object put(String key, Object value) { diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/FieldWrapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/FieldWrapper.java index 59dfc80f..21f7c28e 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/FieldWrapper.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/FieldWrapper.java @@ -26,6 +26,7 @@ public class FieldWrapper { private Class fieldType; private Class mappingType; + private Method getterMethod; private Method setterMethod; public static FieldWrapper of(Class clazz, String fieldName) { @@ -49,10 +50,11 @@ public class FieldWrapper { throw new IllegalStateException("Can not find field \"" + fieldName + "\" in class: " + clazz); } + String setterName = "set" + StringUtil.firstCharToUpperCase(fieldName); Method setter = ClassUtil.getFirstMethod(clazz, method -> method.getParameterCount() == 1 && Modifier.isPublic(method.getModifiers()) - && method.getName().equals("set" + StringUtil.firstCharToUpperCase(fieldName))); + && method.getName().equals(setterName)); if (setter == null) { throw new IllegalStateException("Can not find method \"set" + StringUtil.firstCharToUpperCase(fieldName) + "\" in class: " + clazz); @@ -63,6 +65,11 @@ public class FieldWrapper { fieldWrapper.mappingType = parseMappingType(findField); fieldWrapper.setterMethod = setter; + String[] getterNames = new String[]{"get" + StringUtil.firstCharToUpperCase(fieldName), "is" + StringUtil.firstCharToUpperCase(fieldName)}; + fieldWrapper.getterMethod = ClassUtil.getFirstMethod(clazz, method -> method.getParameterCount() == 0 + && Modifier.isPublic(method.getModifiers()) + && ArrayUtil.contains(getterNames, method.getName())); + wrapperMap.put(fieldName, fieldWrapper); } } @@ -97,6 +104,14 @@ public class FieldWrapper { } } + public Object get(Object target) { + try { + return getterMethod.invoke(target); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public Class getFieldType() { return fieldType; } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java index 80f9114a..2cf249ba 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/MapperUtil.java @@ -21,6 +21,7 @@ import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.field.FieldQuery; import com.mybatisflex.core.field.FieldQueryBuilder; import com.mybatisflex.core.query.*; +import com.mybatisflex.core.relation.RelationManager; import org.apache.ibatis.exceptions.TooManyResultsException; import org.apache.ibatis.session.defaults.DefaultSqlSession; @@ -165,7 +166,18 @@ public class MapperUtil { } - private static Class getWrapType(Class type) { + public static Entity queryRelations(BaseMapper mapper, Entity entity) { + queryRelations(mapper,Collections.singletonList(entity)); + return entity; + } + + public static List queryRelations(BaseMapper mapper, List entities) { + RelationManager.queryRelations(mapper, entities); + return entities; + } + + + public static Class getWrapType(Class type) { if (ClassUtil.canInstance(type.getModifiers())) { return type; } diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Account.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Account.java new file mode 100644 index 00000000..9aa5fbdb --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Account.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ + +package com.mybatisflex.test.relation.onetoone; + +import com.mybatisflex.annotation.*; + +import java.io.Serializable; +import java.util.List; + +@Table(value = "tb_account") +public class Account implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + private String userName; + + private int age; + +// @RelationOneToOne(selfField = "id", targetField = "accountId") + private IDCard idCard; + +// @RelationOneToMany(selfField = "id", targetField = "accountId") + private List books; + + @RelationManyToMany( + joinTable = "tb_role_mapping", + selfField = "id", joinSelfColumn = "account_id", + targetField = "id", joinTargetColumn = "role_id" + ) + private List roles; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public IDCard getIdCard() { + return idCard; + } + + public void setIdCard(IDCard idCard) { + this.idCard = idCard; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + @Override + public String toString() { + return "Account{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", age=" + age + + ", idCard=" + idCard + + ", books=" + books + + ", roles=" + roles + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Book.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Book.java new file mode 100644 index 00000000..ec2487c9 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Book.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ + +package com.mybatisflex.test.relation.onetoone; + +import com.mybatisflex.annotation.RelationManyToOne; +import com.mybatisflex.annotation.Table; + +import java.io.Serializable; + +@Table(value = "tb_book") +public class Book implements Serializable { + + private Long id; + + private Long accountId; + + private String title; + + private String content; + + @RelationManyToOne(selfField = "accountId",targetField = "id") + private Account account; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } + + @Override + public String toString() { + return "Book{" + + "id=" + id + + ", accountId=" + accountId + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", account=" + account + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/IDCard.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/IDCard.java new file mode 100644 index 00000000..9ace096a --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/IDCard.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ + +package com.mybatisflex.test.relation.onetoone; + +import com.mybatisflex.annotation.Table; + +import java.io.Serializable; + +@Table(value = "tb_idcard") +public class IDCard implements Serializable { + + private Long accountId; + + private String cardNo; + + private String content; + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getCardNo() { + return cardNo; + } + + public void setCardNo(String cardNo) { + this.cardNo = cardNo; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @Override + public String toString() { + return "IDCard{" + + "accountId=" + accountId + + ", cardNo='" + cardNo + '\'' + + ", content='" + content + '\'' + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/RelationsTester.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/RelationsTester.java new file mode 100644 index 00000000..4ad946ac --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/RelationsTester.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ +package com.mybatisflex.test.relation.onetoone; + +import com.mybatisflex.core.MybatisFlexBootstrap; +import com.mybatisflex.core.audit.AuditManager; +import com.mybatisflex.core.audit.ConsoleMessageCollector; +import com.mybatisflex.core.audit.MessageCollector; +import com.mybatisflex.core.relation.RelationManager; +import com.mybatisflex.test.relation.mapper.AccountMapper; +import com.mybatisflex.test.relation.mapper.BookMapper; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import javax.sql.DataSource; +import java.util.List; + + +public class RelationsTester { + + static AccountMapper accountMapper; + static BookMapper bookMapper; + + @BeforeClass + public static void init() { + DataSource dataSource = new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("relation/onetoone/schema.sql") + .addScript("relation/onetoone/data.sql") + .build(); + + MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance() + .setDataSource(dataSource) + .addMapper(AccountMapper.class) + .addMapper(BookMapper.class) + .start(); + + //开启审计功能 + AuditManager.setAuditEnable(true); + + //设置 SQL 审计收集器 + MessageCollector collector = new ConsoleMessageCollector(); + AuditManager.setMessageCollector(collector); + + accountMapper = bootstrap.getMapper(AccountMapper.class); + bookMapper = bootstrap.getMapper(BookMapper.class); + } + + + @Test + public void testOneToOne() { + List accounts = accountMapper.selectAll(); + System.out.println(">>>>>>1: " + accounts); + RelationManager.queryRelations(accountMapper, accounts); + System.out.println(">>>>>>2: " + accounts); + } + + + @Test + public void testManyToOne() { + List books = bookMapper.selectAll(); + System.out.println(">>>>>>1: " + books); + RelationManager.queryRelations(bookMapper, books); + System.out.println(">>>>>>2: " + books); + } + + @Test + public void testManyToMany1() { + List accounts = accountMapper.selectAll(); + System.out.println(">>>>>>1: " + accounts); + RelationManager.queryRelations(accountMapper, accounts); + System.out.println(">>>>>>2: " + accounts); + } + + +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Role.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Role.java new file mode 100644 index 00000000..f94fe99c --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/relation/onetoone/Role.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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. + */ + +package com.mybatisflex.test.relation.onetoone; + +import com.mybatisflex.annotation.RelationManyToMany; +import com.mybatisflex.annotation.Table; + +import java.io.Serializable; +import java.util.List; + +@Table(value = "tb_role") +public class Role implements Serializable { + + private Long id; + private String name; + + + @RelationManyToMany( + joinTable = "tb_role_mapping", + selfField = "id", joinSelfColumn = "role_id", + targetField = "id", joinTargetColumn = "account_id" + ) + private List accounts; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getAccounts() { + return accounts; + } + + public void setAccounts(List accounts) { + this.accounts = accounts; + } + + @Override + public String toString() { + return "Role{" + + "id=" + id + + ", name='" + name + '\'' + + ", accounts=" + accounts + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/data.sql b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/data.sql new file mode 100644 index 00000000..498b46dc --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/data.sql @@ -0,0 +1,30 @@ +INSERT INTO tb_account +VALUES (1, '张三', 18), + (2, '王麻子叔叔', 19); + + +INSERT INTO tb_idcard +VALUES (1,'0001', '内容1'), + (2,'0002', '内容2'); + +INSERT INTO tb_book +VALUES (1,1,'图书1', '内容1'), + (2,2,'图书2', '内容2'), + (3,1,'图书3', '内容2'), + (4,1,'图书4', '内容2'), + (5,1,'图书5', '内容2'), + (6,2,'图书6', '内容2'); + + + +INSERT INTO tb_role +VALUES (1,'角色1'), + (2,'角色2'), + (3,'角色3'); + +INSERT INTO tb_role_mapping +VALUES (1,1), + (1,3), + (2,1), + (2,2), + (2,3); diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/schema.sql b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/schema.sql new file mode 100644 index 00000000..5a72e81c --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/relation/onetoone/schema.sql @@ -0,0 +1,35 @@ +CREATE TABLE IF NOT EXISTS `tb_account` +( + `id` INTEGER auto_increment, + `user_name` VARCHAR(100), + `age` Integer +); + + +CREATE TABLE IF NOT EXISTS `tb_idcard` +( + `account_id` Integer, + `card_no` VARCHAR(100), + `content` text +); + + +CREATE TABLE IF NOT EXISTS `tb_book` +( + `id` INTEGER auto_increment, + `account_id` Integer, + `title` VARCHAR(100), + `content` text +); + +CREATE TABLE IF NOT EXISTS `tb_role` +( + `id` INTEGER auto_increment, + `name` VARCHAR(100) +); + +CREATE TABLE IF NOT EXISTS `tb_role_mapping` +( + `account_id` INTEGER , + `role_id` INTEGER +); \ No newline at end of file