在mybatis中自动生成的方法updateByPrimaryKeySelective,表示根据主键修改非Null的属性值,在mongodb中希望实现一个相同的方法
因为可能用2个字段做的联合主键,在mongodb中应该叫唯一索引,所以自定义一个字段注解PrimaryKey
主键注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author: BillYu
* @Description:
* @Date: Created in 09:33 2020-03-09.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface PrimaryKey {
}
在实体类的唯一索引字段加上@PrimaryKey 即可
接口
public interface CustomRepository {
void updateByIdSelective(Object o, Class clazz);
/**
* 根据主键修改不为null的属性值
* @param o
* @return
*/
long updateByPrimaryKeySelective(Object o);
}
实现类
import com.iflytek.voicecloud.yujipc.entity.PrimaryKey;
import com.iflytek.voicecloud.yujipc.repository.CustomRepository;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: BillYu
* @Description:
* @Date: Created in 16:09 2019-12-17.
*/
@Service
public class CustomRepositoryImpl implements CustomRepository {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public void updateByIdSelective(Object o, Class clazz) {
clazz = o.getClass();
String id = null;
Object idValue = null;
Field[] fields = LocalStore.filedMap.get(clazz.getName());
if (fields == null) {
fields = clazz.getDeclaredFields();
//添加本地缓存
LocalStore.filedMap.put(clazz.getName(), fields);
}
Update update = new Update();
//拿到所有的字段,不包括继承的字段
for (Field field : fields) {
//设置可访问,不然拿不到private
field.setAccessible(true);
//配置了注解的话则使用注解名称,作为header字段
field.getName();
try {
if (StringUtils.isEmpty(id)) {
Annotation annotation = field.getAnnotation(Id.class);
if (annotation != null) {
//主键
id = field.getName();
idValue = field.get(o);
}
}
if (!StringUtils.isEmpty(field.getName()) && field.get(o)!=null) {
//非空字段 字段名 字段值
update.set(field.getName(), field.get(o));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Query query = new Query();
Criteria criteria = Criteria.where("_id").is(idValue);
query.addCriteria(criteria);
mongoTemplate.updateFirst(query, update, clazz);
}
@Override
public long updateByPrimaryKeySelective(Object o) {
Class clazz = o.getClass();
Field[] fields = LocalStore.filedMap.get(clazz.getName());
if (fields == null) {
fields = clazz.getDeclaredFields();
//添加本地缓存
LocalStore.filedMap.put(clazz.getName(), fields);
}
Update update = new Update();
//拿到所有的字段,不包括继承的字段
List<Field> keyFields = new ArrayList<>();
for (Field field : fields) {
//设置可访问,不然拿不到private
field.setAccessible(true);
Annotation annotation = field.getAnnotation(PrimaryKey.class);
if (annotation != null) {
//主键
keyFields.add(field);
}
//配置了注解的话则使用注解名称,作为header字段
try {
if (!StringUtils.isEmpty(field.getName()) && field.get(o)!=null) {
//非空字段 字段名 字段值
update.set(field.getName(), field.get(o));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Criteria criteria = null;
for (Field field : keyFields) {
//关注索引顺序
try {
if (criteria == null) {
criteria = Criteria.where(field.getName()).is(field.get(o));
} else {
criteria.and(field.getName()).is(field.get(o));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Query query = new Query();
query.addCriteria(criteria);
UpdateResult updateResult = mongoTemplate.updateFirst(query, update, clazz);
return updateResult.getModifiedCount();
}
}
在repository中继承CustomRepository 即可使用
public interface UserRepository extends MongoRepository<User, ObjectId>,CustomRepository {
}