mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 17:18:24 +08:00
feat: add @RelationManyToMany、@RelationManyToOne@RelationOneToMany@RelationOneToOne annotations
This commit is contained in:
parent
d556ded57e
commit
435248c56b
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 "";
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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();
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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();
|
||||
|
||||
}
|
||||
@ -426,6 +426,58 @@ public interface BaseMapper<T> {
|
||||
return MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据 map 构建的条件来查询数据
|
||||
*
|
||||
* @param map where 条件
|
||||
* @return entity 数据
|
||||
*/
|
||||
default T selectOneWithRelationsByMap(Map<String, Object> 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> R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
|
||||
return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据多个主键来查询多条数据
|
||||
*
|
||||
@ -552,7 +604,7 @@ public interface BaseMapper<T> {
|
||||
return selectObjectListByQueryAs(queryWrapper, asType);
|
||||
}
|
||||
|
||||
if(Map.class.isAssignableFrom(asType)){
|
||||
if (Map.class.isAssignableFrom(asType)) {
|
||||
return (List<R>) selectRowsByQuery(queryWrapper);
|
||||
}
|
||||
|
||||
@ -565,6 +617,14 @@ public interface BaseMapper<T> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据 query 来构建条件查询数据列表,要求返回的数据为 asType
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @param asType 接收的数据类型
|
||||
* @param consumers 字段查询
|
||||
* @return 数据列表
|
||||
*/
|
||||
default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType
|
||||
, Consumer<FieldQueryBuilder<R>>... consumers) {
|
||||
List<R> list = selectListByQueryAs(queryWrapper, asType);
|
||||
@ -577,6 +637,63 @@ public interface BaseMapper<T> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询 entity 及其 relation 注解字段
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
*/
|
||||
default List<T> selectListWithRelationsByQuery(QueryWrapper queryWrapper) {
|
||||
return MapperUtil.queryRelations(this, selectListByQuery(queryWrapper));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询 entity 及其 relation 注解字段
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @param asType 要求返回的数据类型
|
||||
* @return 数据列表
|
||||
*/
|
||||
default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
|
||||
if (Number.class.isAssignableFrom(asType)
|
||||
|| String.class == asType) {
|
||||
return selectObjectListByQueryAs(queryWrapper, asType);
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(asType)) {
|
||||
return (List<R>) selectRowsByQuery(queryWrapper);
|
||||
}
|
||||
|
||||
try {
|
||||
MappedStatementTypes.setCurrentType(asType);
|
||||
return MapperUtil.queryRelations(this, (List<R>) selectListByQuery(queryWrapper));
|
||||
} finally {
|
||||
MappedStatementTypes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询 entity 及其 relation 注解字段
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @param asType 返回的类型
|
||||
* @param consumers 字段查询
|
||||
* @return 数据列表
|
||||
*/
|
||||
default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType
|
||||
, Consumer<FieldQueryBuilder<R>>... consumers) {
|
||||
List<R> 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<T> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询全部数据,及其 relation 字段内容
|
||||
*
|
||||
* @return 数据列表
|
||||
*/
|
||||
default List<T> selectAllWithRelations() {
|
||||
return MapperUtil.queryRelations(this, selectListByQuery(new QueryWrapper()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据 queryWrapper 1 条数据
|
||||
* queryWrapper 执行的结果应该只有 1 列,例如 QueryWrapper.create().select(ACCOUNT.id).where...
|
||||
|
||||
@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<SelfEntity> extends Relation<SelfEntity> {
|
||||
|
||||
private String joinTable;
|
||||
private String joinSelfColumn;
|
||||
private String joinTargetColumn;
|
||||
|
||||
private String orderBy;
|
||||
|
||||
public ManyToMany(RelationManyToMany annotation, Class<SelfEntity> 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<SelfEntity> selfEntities) {
|
||||
Set<Object> 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<SelfEntity> selfEntities, List<?> mappingObjectList, BaseMapper<?> mapper) {
|
||||
List<Row> mappingRows = (List<Row>) mappingObjectList;
|
||||
Set<Object> 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<String> 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<Object> 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<SelfEntity> extends Relation<SelfEntity> {
|
||||
|
||||
public ManyToOne(RelationManyToOne annotation, Class<SelfEntity> entityClass, Field relationField) {
|
||||
super(annotation.selfField(), annotation.targetField(), entityClass, relationField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryWrapper toQueryWrapper(List<SelfEntity> selfEntities) {
|
||||
Set<Object> 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<SelfEntity> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<SelfEntity> extends Relation<SelfEntity> {
|
||||
|
||||
private String orderBy;
|
||||
private int limit;
|
||||
|
||||
|
||||
public OneToMany(RelationOneToMany annotation, Class<SelfEntity> entityClass, Field relationField) {
|
||||
super(annotation.selfField(), annotation.targetField(), entityClass, relationField);
|
||||
this.orderBy = annotation.orderBy();
|
||||
this.limit = annotation.limit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryWrapper toQueryWrapper(List<SelfEntity> selfEntities) {
|
||||
Set<Object> 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<SelfEntity> selfEntities, List<?> targetObjectList, BaseMapper<?> mapper) {
|
||||
selfEntities.forEach(selfEntity -> {
|
||||
Object selfValue = selfFieldWrapper.get(selfEntity);
|
||||
if (selfValue != null) {
|
||||
Class<?> wrapType = MapperUtil.getWrapType(relationFieldWrapper.getFieldType());
|
||||
Collection<Object> 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<SelfEntity> extends Relation<SelfEntity> {
|
||||
|
||||
public OneToOne(RelationOneToOne annotation, Class<SelfEntity> entityClass, Field relationField) {
|
||||
super(annotation.selfField(), annotation.targetField(), entityClass, relationField);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QueryWrapper toQueryWrapper(List<SelfEntity> selfEntities) {
|
||||
Set<Object> 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<SelfEntity> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<SelfEntity> {
|
||||
|
||||
protected Class<SelfEntity> 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<SelfEntity> 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<SelfEntity> getSelfEntityClass() {
|
||||
return selfEntityClass;
|
||||
}
|
||||
|
||||
public void setSelfEntityClass(Class<SelfEntity> 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<Object> getSelfFieldValues(List<SelfEntity> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
Set<Object> 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<SelfEntity> selfEntities);
|
||||
|
||||
public abstract void map(List<SelfEntity> selfEntities, List<?> mappedObjectList, BaseMapper<?> mapper);
|
||||
|
||||
public Class<?> getMappingType() {
|
||||
return relationFieldWrapper.getMappingType();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<Class<?>, List<Relation>> classRelations = new ConcurrentHashMap<>();
|
||||
|
||||
private static List<Relation> getRelations(Class<?> clazz) {
|
||||
return MapUtil.computeIfAbsent(classRelations, clazz, RelationManager::doGetRelations);
|
||||
}
|
||||
|
||||
private static List<Relation> doGetRelations(Class<?> entityClass) {
|
||||
List<Field> allFields = ClassUtil.getAllFields(entityClass);
|
||||
List<Relation> 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 <Entity> void queryRelations(BaseMapper<?> mapper, List<Entity> entities) {
|
||||
if (CollectionUtil.isEmpty(entities)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<Entity> objectClass = (Class<Entity>) entities.get(0).getClass();
|
||||
List<Relation> 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -130,6 +130,21 @@ public class Row extends LinkedHashMap<String, Object> 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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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> Entity queryRelations(BaseMapper<?> mapper, Entity entity) {
|
||||
queryRelations(mapper,Collections.singletonList(entity));
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static <Entity> List<Entity> queryRelations(BaseMapper<?> mapper, List<Entity> entities) {
|
||||
RelationManager.queryRelations(mapper, entities);
|
||||
return entities;
|
||||
}
|
||||
|
||||
|
||||
public static Class<?> getWrapType(Class<?> type) {
|
||||
if (ClassUtil.canInstance(type.getModifiers())) {
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<Book> books;
|
||||
|
||||
@RelationManyToMany(
|
||||
joinTable = "tb_role_mapping",
|
||||
selfField = "id", joinSelfColumn = "account_id",
|
||||
targetField = "id", joinTargetColumn = "role_id"
|
||||
)
|
||||
private List<Role> 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<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
public void setBooks(List<Book> books) {
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public List<Role> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<Role> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Account{" +
|
||||
"id=" + id +
|
||||
", userName='" + userName + '\'' +
|
||||
", age=" + age +
|
||||
", idCard=" + idCard +
|
||||
", books=" + books +
|
||||
", roles=" + roles +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<Account> accounts = accountMapper.selectAll();
|
||||
System.out.println(">>>>>>1: " + accounts);
|
||||
RelationManager.queryRelations(accountMapper, accounts);
|
||||
System.out.println(">>>>>>2: " + accounts);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testManyToOne() {
|
||||
List<Book> books = bookMapper.selectAll();
|
||||
System.out.println(">>>>>>1: " + books);
|
||||
RelationManager.queryRelations(bookMapper, books);
|
||||
System.out.println(">>>>>>2: " + books);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManyToMany1() {
|
||||
List<Account> accounts = accountMapper.selectAll();
|
||||
System.out.println(">>>>>>1: " + accounts);
|
||||
RelationManager.queryRelations(accountMapper, accounts);
|
||||
System.out.println(">>>>>>2: " + accounts);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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<Account> 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<Account> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public void setAccounts(List<Account> accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Role{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", accounts=" + accounts +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
@ -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
|
||||
);
|
||||
Loading…
x
Reference in New Issue
Block a user