From dbe6191ec330f391c8b48a270492d032641dd3ca Mon Sep 17 00:00:00 2001 From: SonderTara Date: Sat, 11 Jun 2022 16:01:16 +0800 Subject: [PATCH 1/3] perf: remove unused class and method. --- .../TableClassCache.java} | 159 +++++++++++------- .../joya/core/builder/SelectBuilder.java | 6 +- .../joya/core/builder/WhereBuilder.java | 8 - .../sondertara/joya/core/jdbc/JoyaJdbc.java | 19 ++- .../joya/core/jdbc/mapper/BeanRowMapper.java | 4 +- .../joya/core/model/TableEntity.java | 2 +- .../core/query/NativeSqlQueryBuilder.java | 18 +- .../core/query/criterion/WhereCriterion.java | 4 +- .../query/pagination/JoyaPageConvert.java | 18 +- .../joya/core/query/pagination/JoyaQuery.java | 24 +-- .../core/query/pagination/PageQueryParam.java | 42 ++++- .../core/query/pagination/SearchParam.java | 3 + .../com/sondertara/joya/domain/Model.java | 1 + .../sondertara/joya/domain/PersistEntity.java | 22 +++ .../joya/hibernate/type/JsonType.java | 3 +- .../SimpleBatchPreparedStatementSetter.java | 47 ++++++ .../com/sondertara/joya/utils/BeanUtil.java | 2 +- .../com/sondertara/joya/utils/SqlUtils.java | 2 + .../joya/utils/idgenerate/IdGen.java | 16 +- 19 files changed, 269 insertions(+), 131 deletions(-) rename src/main/java/com/sondertara/joya/{utils/ClassUtils.java => cache/TableClassCache.java} (55%) create mode 100644 src/main/java/com/sondertara/joya/domain/PersistEntity.java create mode 100644 src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java diff --git a/src/main/java/com/sondertara/joya/utils/ClassUtils.java b/src/main/java/com/sondertara/joya/cache/TableClassCache.java similarity index 55% rename from src/main/java/com/sondertara/joya/utils/ClassUtils.java rename to src/main/java/com/sondertara/joya/cache/TableClassCache.java index 3fa7e35..f37ff6a 100644 --- a/src/main/java/com/sondertara/joya/utils/ClassUtils.java +++ b/src/main/java/com/sondertara/joya/cache/TableClassCache.java @@ -1,29 +1,51 @@ -package com.sondertara.joya.utils; +package com.sondertara.joya.cache; +import com.google.common.collect.Maps; import com.sondertara.common.exception.TaraException; import com.sondertara.common.util.StringUtils; import com.sondertara.joya.core.model.TableEntity; +import com.sondertara.joya.utils.cache.GuavaAbstractLoadingCache; +import com.sondertara.joya.utils.cache.ILocalCache; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import javax.persistence.Transient; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; /** * @author skydu */ -public class ClassUtils { +public class TableClassCache extends GuavaAbstractLoadingCache, Map> implements ILocalCache, Map> { + + private static volatile TableClassCache cache = null; + + private TableClassCache() { + setMaximumSize(1000); + setExpireAfterWriteDuration(60 * 60); + } + + + public synchronized static TableClassCache getInstance() { + if (null == cache) { + synchronized (TableClassCache.class) { + if (null == cache) { + cache = new TableClassCache(); + } + } + } + return cache; + } /** * @return get current classloader @@ -37,7 +59,7 @@ public static ClassLoader getDefaultClassLoader() { } if (cl == null) { // No thread context class loader -> use class loader of this class. - cl = ClassUtils.class.getClassLoader(); + cl = TableClassCache.class.getClassLoader(); if (cl == null) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { @@ -57,8 +79,8 @@ public static ClassLoader getDefaultClassLoader() { * @param clazz class * @return field */ - public static List getFieldList(Class clazz) { - List fields = new ArrayList<>(); + public static Map getAllFields(Class clazz) { + Map fields = Maps.newLinkedHashMap(); Set filedNames = new HashSet<>(); for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { try { @@ -69,7 +91,7 @@ public static List getFieldList(Class clazz) { continue; } filedNames.add(field.getName()); - fields.add(field); + fields.put(field.getName(), field); } } catch (Exception e) { throw new TaraException(e); @@ -78,6 +100,7 @@ public static List getFieldList(Class clazz) { return fields; } + /** * 获取一个实体类对应数据库字段 * @@ -85,9 +108,9 @@ public static List getFieldList(Class clazz) { * @param the class type of bean * @return the table data */ - public static TableEntity getTable(T bean, boolean readData) { + public TableEntity getTable(T bean, boolean readData) { Map filedNames = new LinkedHashMap<>(); - Map relation = new HashMap<>(); + Map relation = Maps.newHashMap(); Class clazz = bean.getClass(); Table table = clazz.getAnnotation(Table.class); String tableName = null; @@ -102,47 +125,56 @@ public static TableEntity getTable(T bean, boolean readData) { if (null == tableName) { throw new TaraException("No [@Table] or [@Entity] annotation found for class->" + clazz); } - TableEntity tableDTO = new TableEntity(); tableDTO.setTableName(tableName); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - try { - Field[] list = c.getDeclaredFields(); - for (Field field : list) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - field.setAccessible(true); - String name = field.getName(); - name = StringUtils.toUnderlineCase(name); - Column column = field.getAnnotation(Column.class); - if (null != column) { - name = column.name(); - } - Id id = field.getAnnotation(Id.class); - if (null != id) { - tableDTO.setPrimaryKey(name); - tableDTO.setPrimaryKeyType(field.getType()); - } - if (filedNames.containsKey(name)) { - continue; - } - if (readData) { - filedNames.put(name, field.get(bean)); + Optional> optional = get(clazz); + return optional.map(fields -> { + for (Field field : fields.values()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + if (field.isAnnotationPresent(Transient.class) || field.isAnnotationPresent(org.springframework.data.annotation.Transient.class)) { + continue; + } + String name = field.getName(); + name = StringUtils.toUnderlineCase(name); + Column column = field.getAnnotation(Column.class); + if (null != column) { + name = column.name(); + } + Id id = field.getAnnotation(Id.class); + if (null != id) { + tableDTO.setPrimaryKey(name); + tableDTO.setPrimaryKeyType(field.getType()); + } + if (filedNames.containsKey(name)) { + continue; + } + if (readData) { + try { + Object o; + if (field.isAccessible()) { + o = field.get(bean); + } else { + field.setAccessible(true); + o = field.get(bean); + field.setAccessible(false); + } + filedNames.put(name, o); + } catch (Exception e) { + e.printStackTrace(); } - relation.put(name, field.getName()); } - } catch (Exception e) { - throw new TaraException(e); + relation.put(name, field.getName()); + } - } + tableDTO.setData(filedNames); + tableDTO.setRelation(relation); + return tableDTO; + }).orElseThrow(() -> new TaraException("Get Class definition error")); - tableDTO.setData(filedNames); - tableDTO.setRelation(relation); - return tableDTO; } - /** * @param clazz * @return the super class @@ -169,24 +201,8 @@ public static Class getSuperClassGenricType(Class clazz) { * @return the current Field */ public static Field getField(Class clazz, String fieldName) { - List fields = getFieldList(clazz); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - return null; - } - - - public static Field getExistedField(Class clazz, String fieldName) { - List fields = getFieldList(clazz); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - throw new TaraException("No such field " + fieldName + "/" + clazz.getSimpleName()); + Map map = getAllFields(clazz); + return map.get(fieldName); } public static Class classForName(String name) throws ClassNotFoundException { @@ -199,4 +215,23 @@ public static Class classForName(String name) throws ClassNotFoundException { } return Class.forName(name); } + + @Override + protected Map fetchData(Class key) { + return getAllFields(key); + } + + @Override + public Optional> get(Class key) { + try { + return Optional.ofNullable(getValue(key)); + } catch (ExecutionException e) { + throw new TaraException(e); + } + } + + @Override + public void remove(Class key) { + + } } diff --git a/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java b/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java index 67a848d..cdf79d6 100644 --- a/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/SelectBuilder.java @@ -27,7 +27,7 @@ public interface SelectBuilder { /** * sql select part *

- * this function will query all columns (select *),you can use {@link #specificS} together to assign alias + * this function will query all columns (select *),you can use {@link #wrapColumn(String...)} together to assign alias *

* 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置specificS来指定字段别名 * @@ -43,7 +43,7 @@ public interface SelectBuilder { * @param selectFields the special column,usually is the column alias * @return this builder */ - SelectBuilder specificS(String... selectFields); + SelectBuilder wrapColumn(String... selectFields); /** * select single column @@ -117,7 +117,7 @@ public interface SelectBuilder { FromBuilder select(TaraFunction f1, TaraFunction f2, TaraFunction f3, TaraFunction f4, TaraFunction f5, TaraFunction f6, TaraFunction f7, TaraFunction f8, TaraFunction f9, TaraFunction f10, TaraFunction f11, TaraFunction f12); /** - * the lambda select, use {@link #specificS(String...)} the resolve alias + * the lambda select, use {@link #wrapColumn(String...)} (String...)} the resolve alias * lambda select 同样冲突字段需要调用specificS() * * @param func select field diff --git a/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java b/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java index 43c4f2c..3cb373e 100644 --- a/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java +++ b/src/main/java/com/sondertara/joya/core/builder/WhereBuilder.java @@ -31,12 +31,4 @@ public interface WhereBuilder extends ExtPartBuilder { */ ExtPartBuilder where(UnaryOperator func, boolean linkOr); - /** - * where 字段追加 一般用于特殊sql,如联表查询条件、特殊sql处理 - * 指定字段的别名 - * - * @param whereFields 特殊字段 - * @return this builder - */ - WhereBuilder specificW(String... whereFields); } \ No newline at end of file diff --git a/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java b/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java index d1cdab6..6796105 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/JoyaJdbc.java @@ -3,6 +3,7 @@ import com.sondertara.common.exception.TaraException; import com.sondertara.common.util.StringFormatter; +import com.sondertara.joya.cache.TableClassCache; import com.sondertara.joya.core.jdbc.mapper.BeanRowMapper; import com.sondertara.joya.core.jdbc.mapper.ListRecordMapper; import com.sondertara.joya.core.jdbc.mapper.MapRowMapper; @@ -11,7 +12,6 @@ import com.sondertara.joya.core.jdbc.mapper.SingleColumnRowMapper; import com.sondertara.joya.core.jdbc.mapper.SingleRowRecordMapper; import com.sondertara.joya.core.model.TableEntity; -import com.sondertara.joya.utils.ClassUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +36,7 @@ */ public class JoyaJdbc { - private static final Logger LOG = LoggerFactory.getLogger(JoyaJdbc.class); + private static final Logger log = LoggerFactory.getLogger(JoyaJdbc.class); private final ConnectionManager connManager; /** @@ -86,7 +86,7 @@ public T query(String sql, RecordMapper recordMapper, Object... params) { return recordMapper.map(new RecordAdapterForResultSet(rs)); } } catch (Exception e) { - LOG.error("query sql error,sql:{}", sql, e); + log.error("query sql error,sql:{}", sql, e); throw new TaraException(e); } finally { connManager.close(conn); @@ -184,7 +184,7 @@ public int update(String sql) { return stmt.executeUpdate(sql); } } catch (Exception e) { - LOG.error("update sql error,sql:{}", sql, e); + log.error("update sql error,sql:{}", sql, e); throw new TaraException(e); } finally { connManager.close(conn); @@ -239,7 +239,7 @@ public Object insert(String sql, Object... params) { } public Object saveEntityIgnoreNull(T entity) { - TableEntity table = ClassUtils.getTable(entity.getClass(), true); + TableEntity table = TableClassCache.getInstance().getTable(entity, true); Map data = table.getData(); Map newData = new LinkedHashMap<>(); for (Map.Entry entry : data.entrySet()) { @@ -253,11 +253,12 @@ public Object saveEntityIgnoreNull(T entity) { public Object saveEntity(T entity) { - TableEntity table = ClassUtils.getTable(entity, true); + TableEntity table = TableClassCache.getInstance().getTable(entity, true); return save(table); } + /** * 执行sql命令, 失败则抛出DbException * @@ -271,7 +272,7 @@ public void execute(String sql) { stmt.execute(sql); } } catch (Exception e) { - LOG.error("execute sql error,sql:{}", sql, e); + log.error("execute sql error,sql:{}", sql, e); throw new TaraException(e); } finally { connManager.close(conn); @@ -320,7 +321,7 @@ public T doInTransaction(ConnectionCallback action) { this.commit(); return t; } catch (Exception e) { - LOG.error("TransactionCallback", e); + log.error("TransactionCallback", e); this.rollback(); throw new TaraException(e); } @@ -343,7 +344,7 @@ public T doInStatement(StatementCallback action) { return t; } } catch (Exception e) { - LOG.error("TransactionCallback", e); + log.error("TransactionCallback", e); throw new TaraException(e); } finally { connManager.close(conn); diff --git a/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java b/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java index ef50827..3cb645c 100644 --- a/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java +++ b/src/main/java/com/sondertara/joya/core/jdbc/mapper/BeanRowMapper.java @@ -1,9 +1,9 @@ package com.sondertara.joya.core.jdbc.mapper; import com.sondertara.common.util.StringUtils; +import com.sondertara.joya.cache.TableClassCache; import com.sondertara.joya.core.jdbc.Row; import com.sondertara.joya.core.model.TableEntity; -import com.sondertara.joya.utils.ClassUtils; import javax.persistence.Entity; import javax.persistence.Table; @@ -30,7 +30,7 @@ public T map(Row row) { T bean = type.getDeclaredConstructor().newInstance(); TableEntity tableEntity = null; if (type.isAnnotationPresent(Table.class) || type.isAnnotationPresent(Entity.class)) { - tableEntity = ClassUtils.getTable(bean, false); + tableEntity = TableClassCache.getInstance().getTable(bean, false); } for (int i = 1; i <= count; i++) { String propertyName; diff --git a/src/main/java/com/sondertara/joya/core/model/TableEntity.java b/src/main/java/com/sondertara/joya/core/model/TableEntity.java index 4608226..6a0bd4e 100644 --- a/src/main/java/com/sondertara/joya/core/model/TableEntity.java +++ b/src/main/java/com/sondertara/joya/core/model/TableEntity.java @@ -32,7 +32,7 @@ public class TableEntity implements Serializable { private Map data; /** * the relation of column and the field - * + *

* key is column name ,value is the field name */ private Map relation; diff --git a/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java b/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java index cecd524..4f4a39d 100644 --- a/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java +++ b/src/main/java/com/sondertara/joya/core/query/NativeSqlQueryBuilder.java @@ -90,7 +90,7 @@ public FromBuilder select(String... columns) { } /** - * 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置specificS来指定字段别名 + * 查询表的全部列,对于联表查询 如果字段名字有重复,只保留前面一个字段,可以配置 {@link NativeSqlQueryBuilder#wrapColumn(String...)} ()}wrapColumn来指定字段别名 */ @Override public FromBuilder select() { @@ -103,7 +103,7 @@ public FromBuilder select() { * @param selectFields 特殊字段 */ @Override - public SelectBuilder specificS(String... selectFields) { + public SelectBuilder wrapColumn(String... selectFields) { this.specificS = Lists.newArrayList(selectFields); return this; } @@ -121,19 +121,7 @@ public FromBuilder select(TaraFunction f1) { return this; } - /** - * where 字段追加 一般用于特殊sql,如联表查询条件、特殊sql处理 - * 指定字段的别名 - * - * @param whereFields 特殊字段 - */ - @Override - public WhereBuilder specificW(String... whereFields) { - for (String whereField : whereFields) { - this.where.specificW(whereField); - } - return this; - } + /** diff --git a/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java b/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java index bbfb130..2d7b086 100644 --- a/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java +++ b/src/main/java/com/sondertara/joya/core/query/criterion/WhereCriterion.java @@ -41,7 +41,7 @@ public class WhereCriterion { /** * the link type for where segments */ - private Operator currentOpt; + private final Operator currentOpt; /** * 默认用 and 连接 查询条件 @@ -639,7 +639,7 @@ public WhereCriterion notBetween(TaraFunction fn, List values) /** * 追加到 where条件中自定义sql字符串片段 */ - public void specificW(String part) { + public void addCondition(String part) { this.segments.add(SqlUtils.underlineColumn(part)); } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java index f33efb1..8a63309 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaPageConvert.java @@ -1,7 +1,7 @@ package com.sondertara.joya.core.query.pagination; +import com.sondertara.common.util.CollectionUtils; import com.sondertara.common.util.StringFormatter; -import com.sondertara.common.util.StringUtils; import com.sondertara.joya.core.query.NativeSqlQuery; import com.sondertara.joya.core.query.NativeSqlQueryBuilder; import com.sondertara.joya.core.query.criterion.JoinCriterion; @@ -50,8 +50,10 @@ public static NativeSqlQuery buildNativeQuery(PageQueryParam queryParam, Class joinFunc, Class... targetClass) { List searchParams = queryParam.getParams(); UnaryOperator func = w -> { - if (StringUtils.isNotBlank(queryParam.getSpecificW())) { - w.specificW(queryParam.getSpecificW()); + if (CollectionUtils.isNotEmpty(queryParam.getCondition())) { + for (String s : queryParam.getCondition()) { + w.addCondition(s); + } } for (SearchParam searchParam : searchParams) { String fieldName = searchParam.getFieldName(); @@ -96,14 +98,10 @@ private static NativeSqlQuery buildNativeQuery(PageQueryParam queryParam, UnaryO return w; }; NativeSqlQueryBuilder builder = new NativeSqlQueryBuilder(); - if (null != queryParam.getSelect()) { - builder.select(queryParam.getSelect()); - } else { - if (null != queryParam.getSpecificS()) { - builder.specificS(queryParam.getSpecificS().toArray(new String[0])); - } - builder.select(); + if (null != queryParam.getColumns()) { + builder.wrapColumn(queryParam.getColumns().toArray(new String[0])); } + builder.select(); if (null != targetClass && targetClass.length > 0) { builder.from(targetClass); } else { diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java index ecf99b4..19fc480 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/JoyaQuery.java @@ -3,6 +3,7 @@ import com.google.common.collect.Lists; import lombok.Data; +import java.util.ArrayList; import java.util.List; /** @@ -13,29 +14,30 @@ @Data public abstract class JoyaQuery { - /** * 特殊where语句 */ - public String specificW; + protected List condition = new ArrayList<>(); + /** - * 指定select语句 + * 指定from */ - public String select; + protected String from; /** * 特殊select 用来指定重名字段的别名 */ - public List specificS; + protected List columns; - public List getSpecificS() { - return specificS; + protected List getCondition() { + return condition; } - public void setSpecificS(String... specificS) { - this.specificS = Lists.newArrayList(specificS); + public void addCondition(String condition) { + this.condition.add(condition); } - public void setSpecificF(String... specificF) { - this.specificS = Lists.newArrayList(specificF); + + public void column(String... columns) { + this.columns = Lists.newArrayList(columns); } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java index 1e04e37..bc67dfc 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/PageQueryParam.java @@ -1,7 +1,6 @@ package com.sondertara.joya.core.query.pagination; import com.google.common.collect.Lists; -import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; @@ -15,7 +14,6 @@ * @version 1.0 2020年12月 */ @EqualsAndHashCode(callSuper = true) -@Data public class PageQueryParam extends JoyaQuery implements Serializable { /** * page size @@ -63,4 +61,44 @@ public void addSearchParam(String filed, Object value, FieldParam.Operator opera this.params.add(new SearchParam(filed, value, operator)); } + + public Integer getPageSize() { + return pageSize; + } + + public void pageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + public Integer getPage() { + return page; + } + + public void page(Integer page) { + this.page = page; + } + + public void linkType(LinkType linkType) { + this.linkType = linkType; + } + + public void setParams(List params) { + this.params = params; + } + + public List getParams() { + return params; + } + + public LinkType getLinkType() { + return linkType; + } + + public List getOrderList() { + return orderList; + } + + public void setOrderList(List orderList) { + this.orderList = orderList; + } } diff --git a/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java b/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java index cfe4b35..07c07d5 100644 --- a/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java +++ b/src/main/java/com/sondertara/joya/core/query/pagination/SearchParam.java @@ -1,10 +1,13 @@ package com.sondertara.joya.core.query.pagination; +import lombok.ToString; + import java.io.Serializable; /** * @author huangxiaohu */ +@ToString public class SearchParam implements Serializable { private static final long serialVersionUID = -2687523337885804193L; private String fieldName; diff --git a/src/main/java/com/sondertara/joya/domain/Model.java b/src/main/java/com/sondertara/joya/domain/Model.java index fcb62fa..77fe060 100644 --- a/src/main/java/com/sondertara/joya/domain/Model.java +++ b/src/main/java/com/sondertara/joya/domain/Model.java @@ -67,6 +67,7 @@ public T save() { * * @return 查询到的对象 */ + public T findById() { return getRepository().findById(Objects.requireNonNull(getId())).orElseThrow(() -> new NullPointerException("ID is null")); } diff --git a/src/main/java/com/sondertara/joya/domain/PersistEntity.java b/src/main/java/com/sondertara/joya/domain/PersistEntity.java new file mode 100644 index 0000000..2358a14 --- /dev/null +++ b/src/main/java/com/sondertara/joya/domain/PersistEntity.java @@ -0,0 +1,22 @@ +package com.sondertara.joya.domain; + +import javax.persistence.Transient; +import java.io.Serializable; + +/** + * 通用实体,属性不会映射到数据库 + * + * @author huangxiaohu + */ +public class PersistEntity implements Serializable { + @Transient + private boolean isNew = true; + + public boolean isNew() { + return isNew; + } + + public void setNew(boolean aNew) { + isNew = aNew; + } +} diff --git a/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java b/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java index c894369..b88f7ce 100644 --- a/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java +++ b/src/main/java/com/sondertara/joya/hibernate/type/JsonType.java @@ -3,7 +3,6 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.sondertara.common.util.StringUtils; -import com.sondertara.joya.utils.ClassUtils; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.CoreMessageLogger; @@ -218,7 +217,7 @@ public void setParameterValues(Properties parameters) { parseSqlType(reader.getAnnotationsMethod()); } else { try { - type = ClassUtils.classForName((String) parameters.get(CLASS_NAME)); + type = org.apache.commons.lang3.ClassUtils.getClass((String) parameters.get(CLASS_NAME)); } catch (ClassNotFoundException exception) { throw new HibernateException("class not found", exception); } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java b/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java new file mode 100644 index 0000000..ade3960 --- /dev/null +++ b/src/main/java/com/sondertara/joya/jpa/repository/statment/SimpleBatchPreparedStatementSetter.java @@ -0,0 +1,47 @@ +package com.sondertara.joya.jpa.repository.statment; + +import com.sondertara.joya.core.model.TableEntity; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.SqlParameterValue; +import org.springframework.jdbc.core.SqlTypeValue; +import org.springframework.jdbc.core.StatementCreatorUtils; +import org.springframework.lang.NonNull; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * @author huangxiaohu + */ +public class SimpleBatchPreparedStatementSetter implements BatchPreparedStatementSetter { + + + private final List rows; + + public SimpleBatchPreparedStatementSetter(List rows) { + this.rows = rows; + } + + @Override + public void setValues(@NonNull PreparedStatement ps, int i) throws SQLException { + TableEntity table = rows.get(i); + Map data = table.getData(); + int colIndex = 0; + for (Object value : data.values()) { + colIndex++; + if (value instanceof SqlParameterValue) { + SqlParameterValue paramValue = (SqlParameterValue) value; + StatementCreatorUtils.setParameterValue(ps, colIndex, paramValue, paramValue.getValue()); + } else { + StatementCreatorUtils.setParameterValue(ps, colIndex, SqlTypeValue.TYPE_UNKNOWN, value); + } + } + } + + @Override + public int getBatchSize() { + return this.rows.size(); + } +} diff --git a/src/main/java/com/sondertara/joya/utils/BeanUtil.java b/src/main/java/com/sondertara/joya/utils/BeanUtil.java index 957bca6..12657fc 100644 --- a/src/main/java/com/sondertara/joya/utils/BeanUtil.java +++ b/src/main/java/com/sondertara/joya/utils/BeanUtil.java @@ -26,7 +26,7 @@ public abstract class BeanUtil extends org.springframework.beans.BeanUtils { /** * 修改spring的BeanUtils,不用null覆盖已有的值 */ - public static void copyProperties(Object source, Object target) throws BeansException { + public static void copyPropertiesIgnoreNull(Object source, Object target) throws BeansException { Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); Class clazz = target.getClass(); diff --git a/src/main/java/com/sondertara/joya/utils/SqlUtils.java b/src/main/java/com/sondertara/joya/utils/SqlUtils.java index e135e03..9ec6947 100644 --- a/src/main/java/com/sondertara/joya/utils/SqlUtils.java +++ b/src/main/java/com/sondertara/joya/utils/SqlUtils.java @@ -4,6 +4,7 @@ import com.sondertara.common.util.RegexUtils; import com.sondertara.common.util.StringUtils; import com.sondertara.joya.core.query.NativeSqlQuery; +import lombok.extern.slf4j.Slf4j; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -11,6 +12,7 @@ /** * @author huangxiaohu */ +@Slf4j public class SqlUtils { /** * 左边字段提取 diff --git a/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java b/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java index 008204f..b368bad 100644 --- a/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java +++ b/src/main/java/com/sondertara/joya/utils/idgenerate/IdGen.java @@ -15,9 +15,18 @@ */ public class IdGen implements IdentifierGenerator { - private static final SecureRandom random = new SecureRandom(); - private static final IdWorker idWorker = new IdWorker(-1, -1); + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static IdWorker idWorker = new IdWorker(-1, -1); + /** + * Change the snowflake workId and datacenterId + * + * @param workerId workId + * @param datacenterId datacenterId + */ + public static void setIdWorker(int workerId, int datacenterId) { + idWorker = new IdWorker(workerId, datacenterId); + } /** * 生成UUID, 中间无-分割 @@ -30,7 +39,7 @@ public static String uuid() { * 使用SecureRandom随机生成Long */ public static long randomLong() { - return Math.abs(random.nextLong()); + return Math.abs(SECURE_RANDOM.nextLong()); } /** @@ -41,6 +50,7 @@ public static long snowflake() { } /** + * Generate the id with 18 length * 获取新唯一编号(18位数值) * 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。 * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加)) From 18b6fe9d8183c622fc3767e74b8d323a11b1234c Mon Sep 17 00:00:00 2001 From: SonderTara Date: Sat, 11 Jun 2022 16:03:36 +0800 Subject: [PATCH 2/3] fix: fix issue #3 Use @Transactional annotation to use cglib proxy avoid those errors. --- .../jpa/repository/BaseRepositoryImpl.java | 58 +++--- .../joya/jpa/repository/JoyaRepository.java | 188 +++++++++++++++--- 2 files changed, 185 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java index 04c1b6b..70de820 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/BaseRepositoryImpl.java @@ -7,8 +7,7 @@ import com.sondertara.joya.utils.BeanUtil; import com.sondertara.joya.utils.SqlUtils; import org.apache.commons.beanutils.BeanUtils; -import org.hibernate.Session; -import org.hibernate.query.internal.NativeQueryImpl; +import org.hibernate.query.NativeQuery; import org.hibernate.transform.Transformers; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -77,7 +76,7 @@ public S saveIgnoreNull(@NonNull S entity) { } else { T po = super.findById(((ID) Objects.requireNonNull(eif.getId(entity)))).orElse(null); if (Objects.nonNull(po)) { - BeanUtil.copyProperties(entity, po); + BeanUtil.copyPropertiesIgnoreNull(entity, po); return (S) this.em.merge(po); } return this.em.merge(entity); @@ -140,39 +139,34 @@ private Map toMap(List list) { @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) public List findListBySql(String sql, Class clazz, Object... params) { - Query query = em.unwrap(Session.class).createNativeQuery(sql); + Query query = em.createNativeQuery(sql); setParameters(query, params); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(clazz)).list(); + return query.unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(clazz)).list(); } @Override - @SuppressWarnings("unchecked") public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { - Query query = em.unwrap(Session.class).createNativeQuery(nativeSql.toSql()); - setParameters(query, nativeSql.getParams()); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + return findListBySql(nativeSql.toSql(), resultClass, null != nativeSql.getParams() ? nativeSql.getParams().toArray() : new Object[0]); } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) public Page queryPageBySql(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { String sqlStr = nativeSql.toSql(); //获取总记录数 - Session session = em.unwrap(Session.class); String countSql = SqlUtils.buildCountSql(sqlStr); - Query countQuery = session.createNativeQuery(countSql); + Query countQuery = em.createNativeQuery(countSql); setParameters(countQuery, nativeSql.getParams()); long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); //获取分页结果 - Query pageQuery = session.createNativeQuery(sqlStr); + Query pageQuery = em.createNativeQuery(sqlStr); setParameters(pageQuery, nativeSql.getParams()); - - List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo).setMaxResults(pageSize).unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo).setMaxResults(pageSize).unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); return new PageImpl<>(result, PageRequest.of(pageNo, pageSize), totalRecord); } @@ -190,7 +184,7 @@ public T findOneByHql(final String ql, final Object... params) { } public List findAllByHql(final String ql, final Object... params) { - return findAllByHql(ql, (Pageable) null, params); + return findAllByHql(ql, null, params); } /** @@ -249,7 +243,7 @@ private String prepareOrder(Sort sort) { * 按顺序设置Query参数 */ private void setParameters(Query query, Object[] params) { - if (params != null) { + if (params != null && params.length > 0) { for (int i = 0; i < params.length; i++) { query.setParameter(i + 1, params[i]); } @@ -260,7 +254,7 @@ private void setParameters(Query query, Object[] params) { * 按顺序设置Query参数 */ private void setParameters(Query query, List params) { - if (params != null) { + if (params != null && params.size() > 0) { for (int i = 0; i < params.size(); i++) { query.setParameter(i + 1, params.get(i)); } @@ -290,47 +284,45 @@ public X findListByHql(String queryJql, Map params) { @Override public List> findMapListBySql(NativeSqlQuery nativeSql, boolean camelCase) { - - return findMapListBySql(nativeSql, camelCase); + return findMapListBySql(nativeSql.toSql(), nativeSql.getParams(), camelCase); } @Override public Map findMapBySql(NativeSqlQuery nativeSql, boolean camelCase) { - - return findMapBySql(nativeSql, camelCase); + return findMapBySql(nativeSql.toSql(), nativeSql.getParams(), camelCase); } /** * (non-Javadoc) */ @Override - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked", "deprecation"}) public List> findMapListBySql(String querySql, List params, boolean camelCase) { Query query = em.createNativeQuery(querySql); setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); return query.getResultList(); } @Override - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked", "deprecation"}) public Map findMapBySql(String querySql, List params, boolean camelCase) { Query query = em.createNativeQuery(querySql); setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); return (Map) query.getSingleResult(); } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked", "deprecation"}) @Override public List> findMapListByHql(String querySql, Map params) { Query query = this.createSqlQueryWithNameParam(querySql, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + query.unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); return query.getResultList(); } - @SuppressWarnings("unchecked") @Override + @SuppressWarnings({"unchecked"}) public List findListBySql(String querySql, Map params) { Query query = this.createSqlQueryWithNameParam(querySql, params); return query.getResultList(); @@ -341,7 +333,7 @@ public List findListBySql(String querySql, Map params) { * * @param values 参数Map */ - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({"unchecked"}) public Query createQueryWithNameParam(final String queryJql, final Map values) { Query query = this.em.createQuery(queryJql); @@ -392,13 +384,13 @@ public X findObjectBySql(String querySql, Class clazz, final Map findMapBySql(String querySql, Map params) { Query query = this.createSqlQueryWithNameParam(querySql, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + query.unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); return (Map) query.getSingleResult(); } diff --git a/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java b/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java index 2166e14..dabd7a8 100644 --- a/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java +++ b/src/main/java/com/sondertara/joya/jpa/repository/JoyaRepository.java @@ -1,29 +1,43 @@ package com.sondertara.joya.jpa.repository; +import com.sondertara.common.util.CollectionUtils; +import com.sondertara.common.util.StringFormatter; +import com.sondertara.joya.cache.TableClassCache; +import com.sondertara.joya.core.model.TableEntity; import com.sondertara.joya.core.query.NativeSqlQuery; import com.sondertara.joya.core.query.criterion.JoinCriterion; import com.sondertara.joya.core.query.pagination.JoyaPageConvert; import com.sondertara.joya.core.query.pagination.PageQueryParam; import com.sondertara.joya.core.query.pagination.PageResult; +import com.sondertara.joya.domain.PersistEntity; import com.sondertara.joya.ext.JoyaSpringContext; import com.sondertara.joya.hibernate.transformer.AliasToBeanTransformer; import com.sondertara.joya.hibernate.transformer.AliasToMapResultTransformer; +import com.sondertara.joya.jpa.repository.statment.SimpleBatchPreparedStatementSetter; import com.sondertara.joya.utils.SqlUtils; -import org.hibernate.query.internal.NativeQueryImpl; +import org.hibernate.Session; +import org.hibernate.query.NativeQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.jdbc.support.JdbcUtils; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.Query; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.StringJoiner; import java.util.function.UnaryOperator; +import java.util.stream.Collectors; /** * dao @@ -35,6 +49,9 @@ public class JoyaRepository { private static final Logger log = LoggerFactory.getLogger(JoyaRepository.class); private static final String SQL_VIEW_SWITCH = "joya.sql-view"; + + private static final int BATCH_SIZE = 500; + private final EntityManager em; public JoyaRepository(EntityManager em) { @@ -45,20 +62,20 @@ public JoyaRepository(EntityManager em) { /** * 查询list * - * @param sql 原生sql - * @param clazz 目标实体 - * @param params 参数 - * @param 泛型 + * @param sql 原生sql + * @param resultClass 目标实体 + * @param params 参数 + * @param 泛型 * @return list */ - @SuppressWarnings("unchecked") - public List findListBySql(String sql, Class clazz, Object... params) { + @SuppressWarnings({"unchecked","deprecation"}) + public List findListBySql(String sql, Class resultClass, Object... params) { if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { log.info("[findListBySql] SQL:\nJoya-SQL: {}", sql); } Query query = em.createNativeQuery(sql); setParameters(query, params); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(clazz)).list(); + return query.unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); } /** @@ -69,7 +86,7 @@ public List findListBySql(String sql, Class clazz, Object... params) { * @param generic * @return list */ - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked","deprecation"}) public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) { if (JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, true)) { @@ -77,7 +94,7 @@ public List findListBySql(NativeSqlQuery nativeSql, Class resultClass) } Query query = em.createNativeQuery(nativeSql.toSql()); setParameters(query, nativeSql.getParams()); - return query.unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + return query.unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); } /** @@ -109,19 +126,19 @@ public Map findMapBySql(NativeSqlQuery nativeSql, List p /** * (non-Javadoc) */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked","deprecation"}) public List> findMapListBySql(String querySql, List params, boolean camelCase) { Query query = em.createNativeQuery(querySql); setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); return query.getResultList(); } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked","deprecation"}) public Map findMapBySql(String querySql, List params, boolean camelCase) { Query query = em.createNativeQuery(querySql); setParameters(query, params); - query.unwrap(NativeQueryImpl.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); + query.unwrap(NativeQuery.class).setResultTransformer(AliasToMapResultTransformer.getInstance(camelCase)); return (Map) query.getSingleResult(); } @@ -156,43 +173,55 @@ public PageResult queryPage(PageQueryParam queryParam, Class resultCla } + /** * query page * - * @param nativeSql sql query + * @param sql sql query * @param resultClass result class * @param pageNo page start * @param pageSize page size * @param the type of result + * @param params the query params * @return pagination result */ - @SuppressWarnings("unchecked") - public PageResult queryPage(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { + @SuppressWarnings({"unchecked","deprecation"}) + public PageResult queryPage(String sql, Class resultClass, Integer pageNo, Integer pageSize, Object... params) { Boolean opened = JoyaSpringContext.getConfig(SQL_VIEW_SWITCH, false); - - String sqlStr = nativeSql.toSql(); - if (opened) { - log.info("[queryPage] SQL:\nJoya-SQL: {}", sqlStr); + log.info("[queryPage] SQL:\nJoya-SQL: {}", sql); } - // get the count sql - String countSql = SqlUtils.buildCountSql(sqlStr); + String countSql = SqlUtils.buildCountSql(sql); Query countQuery = em.createNativeQuery(countSql); - setParameters(countQuery, nativeSql.getParams()); + setParameters(countQuery, params); long totalRecord = ((Number) countQuery.getSingleResult()).longValue(); // the query - Query pageQuery = em.createNativeQuery(sqlStr); + Query pageQuery = em.createNativeQuery(sql); - setParameters(pageQuery, nativeSql.getParams()); + setParameters(pageQuery, params); - List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo).setMaxResults(pageSize).unwrap(NativeQueryImpl.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); + List result = totalRecord == 0 ? new ArrayList<>(0) : pageQuery.setFirstResult(pageNo * pageSize).setMaxResults(pageSize).unwrap(NativeQuery.class).setResultTransformer(new AliasToBeanTransformer<>(resultClass)).list(); return new PageResult<>(pageNo, pageSize, totalRecord, result); } + /** + * query page + * + * @param nativeSql sql query + * @param resultClass result class + * @param pageNo page start + * @param pageSize page size + * @param the type of result + * @return pagination result + */ + public PageResult queryPage(NativeSqlQuery nativeSql, Class resultClass, Integer pageNo, Integer pageSize) { + return queryPage(nativeSql.toSql(), resultClass, pageNo, pageSize, null == nativeSql.getParams() ? new Object[0] : nativeSql.getParams().toArray()); + } + /** * 根据ql和按照索引顺序的params查询一个实体 @@ -264,7 +293,7 @@ private String prepareOrder(Sort sort) { * 按顺序设置Query参数 */ private void setParameters(Query query, Object[] params) { - if (params != null) { + if (params != null && params.length > 0) { for (int i = 0; i < params.length; i++) { query.setParameter(i + 1, params[i]); } @@ -281,4 +310,107 @@ private void setParameters(Query query, List params) { } } } + + /** + * Batch update, first execute the update operation, then the insert operation, + * it is not performed in the transaction by default, and support Spring transaction management + * 批量更新,先执行更新操作,后执行插入操作,默认不是在事务中执行,支持Spring事务管理 + *

+ * The pojo need extends {@link PersistEntity},and explicitly specifies whether it is new by the field isNew + * 实体需要继承{@link PersistEntity} 通过isNew字段来表示是否是新建还是更新,默认是新增 + *

+ * 1.对于mysql主键自增这种实体通过重写{@link PersistEntity#isNew()}判断主键是否为null就可以标识是否新增 + * 2.对于通过序列来设置主键值的情形,在构造dataList时,需要显示调用{@link PersistEntity#setNew(boolean)} 来标识是否新增 + * + * @param dataList 数据 + * @param 类型 + */ + @Transactional(readOnly = false, propagation = Propagation.SUPPORTS) + public void batchUpdate(List dataList) throws SQLException { + try { + if (CollectionUtils.isEmpty(dataList)) { + return; + } + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + for (T data : dataList) { + TableEntity table = TableClassCache.getInstance().getTable(data, true); + if (data.isNew() || table.getData().get(table.getPrimaryKey()) == null) { + if (table.getData().get(table.getPrimaryKey()) == null) { + table.getData().remove(table.getPrimaryKey()); + } + insertList.add(table); + } else { + updateList.add(table); + } + } + String insertSql = null; + if (insertList.size() > 0) { + TableEntity table = insertList.get(0); + Map data = table.getData(); + // auto increment + if (null == data.get(table.getPrimaryKey())) { + data.remove(table.getPrimaryKey()); + } + List set = data.keySet().stream().map(s -> "?").collect(Collectors.toList()); + insertSql = StringFormatter.format("insert into {}({}) values({})", table.getTableName(), String.join(",", data.keySet()), String.join(",", set)); + } + String updateSql = null; + if (updateList.size() > 0) { + TableEntity table = updateList.get(0); + StringJoiner sj = new StringJoiner(", "); + Map map = table.getData(); + Object primaryKeyValue = map.remove(table.getPrimaryKey()); + for (String key : map.keySet()) { + sj.add(key + " = ?"); + } + map.put(table.getPrimaryKey(), primaryKeyValue); + updateSql = StringFormatter.format("update {} set {} where {} = ?", table.getTableName(), sj.toString(), table.getPrimaryKey()); + } + try (Session session = em.unwrap(Session.class)) { + String finalUpdateSql = updateSql; + String finalInsertSql = insertSql; + log.info("Batch update start,insert size is:{},update size is:{}", insertList.size(), updateList.size()); + session.doWork(connection -> { + if (null != finalUpdateSql) { + batchUpdate(finalUpdateSql, updateList, connection); + } + if (null != finalInsertSql) { + batchUpdate(finalInsertSql, insertList, connection); + } + }); + } + } catch (Exception e) { + throw new SQLException(e.getMessage(), e.getCause()); + } + + log.info("Batch update completed."); + } + + private void batchUpdate(String sql, List rows, Connection connection) throws SQLException { + if (null == sql) { + return; + } + SimpleBatchPreparedStatementSetter setter = new SimpleBatchPreparedStatementSetter(rows); + PreparedStatement ps = connection.prepareStatement(sql); + int batchSize = setter.getBatchSize(); + if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) { + for (int j = 0; j < batchSize; j++) { + setter.setValues(ps, j); + ps.addBatch(); + if ((j + 1) % BATCH_SIZE == 0 || j == batchSize - 1) { + ps.executeBatch(); + ps.clearBatch(); + } + } + } else { + for (int i = 0; i < batchSize; i++) { + setter.setValues(ps, i); + ps.executeUpdate(); + } + } + if (!ps.isClosed()) { + ps.close(); + } + } } From eb69f24cec477263ae191b18176306d92ddfb518 Mon Sep 17 00:00:00 2001 From: SonderTara Date: Sat, 11 Jun 2022 16:19:48 +0800 Subject: [PATCH 3/3] feat: version v0.1.0 --- README.md | 14 ++++++-------- build.gradle | 3 +-- docs/quick_start.md | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f8f716a..99a9437 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ Maven Project com.sondertara joya - 0.0.7.209 + 0.1.0 ``` Gradle Project ```groovy -implementation 'com.sondertara:joya:0.0.7.209' +implementation 'com.sondertara:joya:0.1.0' ``` ### 2.添加配置 @@ -257,19 +257,17 @@ public class Test { NativeSqlQuery query1 = NativeSqlQuery.builder() .select() .from(j -> j.join(UserPo::getId, UserExtendPo::getUserId)) - .where(w -> w - .eq(UserPo::getUserName, "张三")) + .where(w -> w.eq(UserPo::getUserName, "张三")) .build(); //对于冲突字段可以指定别名,如user表和user_extend表同时有 updateTime字段,可以通过指定别名来避免字段值覆盖 // SELECT t0.id,t0.user_name,t0.user_email,t0.user_phone,t0.update_time,t1.update_time AS modifyTime,t1.account_expired_time,t1.password_expired_time,t1.ext_data FROM user AS t0 JOIN user_extend AS t1 ON t0.id = t1.user_id WHERE t0.user_name = ?1 NativeSqlQuery query3 = NativeSqlQuery.builder() + .wrapColumn("t1.updateTime AS modifyTime") //将user_extend中重名的updateTime 指定为modifyTime .select()//查询全部字段 - .specificS("t1.updateTime AS modifyTime") //将user_extend中重名的updateTime 指定为modifyTime .from(j -> j.join(UserPo::getId, UserExtendPo::getUserId)) - .where(w -> w - .eq(UserPo::getUserName, "张三")) + .where(w -> w.eq(UserPo::getUserName, "张三")) .build(); } } @@ -386,7 +384,7 @@ PageResult pageResult=joyaRepository.queryPage(pageQueryParam,UserDTO.c .endsWith() // like '%a' .contains() // like '%a%' .startsWith() // like 'a%' - .specificS()) //指定特殊的查询语句 + .addCondition()) //指定特殊的查询语句 ``` where 查询语句默认是`AND`条件联接,可以选择`OR`条件联接 diff --git a/build.gradle b/build.gradle index 96aa40c..2545f88 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ allprojects { def isRelease = false group = 'com.sondertara' -version = '0.0.7.209' +version = '0.1.0' archivesBaseName = 'joya' sourceCompatibility = '1.8' @@ -75,7 +75,6 @@ dependencies { implementation 'com.sondertara:common-tara:0.1.0' compileOnly 'org.projectlombok:lombok:1.18.24' compileOnly 'com.oracle.database.jdbc:ojdbc8:21.5.0.0' - annotationProcessor 'org.projectlombok:lombok:1.18.24' } diff --git a/docs/quick_start.md b/docs/quick_start.md index e2cc6e4..de7fa27 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -9,14 +9,14 @@ Maven Project com.sondertara joya - 0.0.7.209 + 0.1.0 ``` Gradle Project ```groovy -implementation 'com.sondertara:joya:0.0.7.209' +implementation 'com.sondertara:joya:0.1.0' ``` ## 新项目集成 :id=new_project