diff --git a/src/main/java/org/redkale/persistence/GeneratedValue.java b/src/main/java/org/redkale/persistence/GeneratedValue.java
new file mode 100644
index 000000000..bd6e42300
--- /dev/null
+++ b/src/main/java/org/redkale/persistence/GeneratedValue.java
@@ -0,0 +1,62 @@
+/** *****************************************************************************
+ * Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Linda DeMichiel - Java Persistence 2.1
+ * Linda DeMichiel - Java Persistence 2.0
+ *
+ ***************************************************************************** */
+package org.redkale.persistence;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.*;
+
+/**
+ * Provides for the specification of generation strategies for the
+ * values of primary keys.
+ *
+ *
+ * The GeneratedValue annotation
+ * may be applied to a primary key property or field of an entity or
+ * mapped superclass in conjunction with the {@link Id} annotation.
+ * The use of the GeneratedValue annotation is only
+ * required to be supported for simple primary keys. Use of the
+ * GeneratedValue annotation is not supported for derived
+ * primary keys.
+ *
+ *
+ *
+ * Example 1:
+ *
+ * @Id
+ * @GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
+ * @Column(name="CUST_ID")
+ * public Long getId() { return id; }
+ *
+ * Example 2:
+ *
+ * @Id
+ * @GeneratedValue(strategy=TABLE, generator="CUST_GEN")
+ * @Column(name="CUST_ID")
+ * Long id;
+ *
+ *
+ * @see Id
+ *
+ * @since Java Persistence 1.0
+ */
+@Target({METHOD, FIELD})
+@Retention(RUNTIME)
+
+public @interface GeneratedValue {
+
+}
diff --git a/src/main/java/org/redkale/source/AbstractDataSqlSource.java b/src/main/java/org/redkale/source/AbstractDataSqlSource.java
index 5bc454573..e160066b8 100644
--- a/src/main/java/org/redkale/source/AbstractDataSqlSource.java
+++ b/src/main/java/org/redkale/source/AbstractDataSqlSource.java
@@ -442,7 +442,9 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
sqltype = column.length >= 65535 ? "TEXT" : ("VARCHAR(" + column.length + ")");
sqlnull = !column.nullable ? "NOT NULL DEFAULT ''" : "NULL";
}
- sb.append(" `").append(column.column).append("` ").append(sqltype).append(" ").append(sqlnull);
+ sb.append(" `").append(column.column).append("` ").append(sqltype)
+ .append(column.primary && info.isAutoGenerated() ? " AUTO_INCREMENT " : " ")
+ .append(column.primary && info.isAutoGenerated() ? "" : sqlnull);
if (column.comment != null && !column.comment.isEmpty()) {
sb.append(" COMMENT '").append(column.comment.replace('\'', '"')).append("'");
}
@@ -552,7 +554,11 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
sqltype = column.length >= 65535 ? "TEXT" : ("VARCHAR(" + column.length + ")");
sqlnull = !column.nullable ? "NOT NULL DEFAULT ''" : "NULL";
}
- sb.append(" ").append(column.column).append(" ").append(sqltype).append(" ").append(sqlnull);
+ if (column.primary && info.isAutoGenerated()) {
+ sqltype = "SERIAL";
+ }
+ sb.append(" ").append(column.column).append(" ").append(sqltype).append(" ")
+ .append(column.primary && info.isAutoGenerated() ? "" : sqlnull);
if (column.comment != null && !column.comment.isEmpty()) {
//postgresql不支持DDL中直接带comment
comments.add("COMMENT ON COLUMN " + info.getOriginTable() + "." + column.column + " IS '" + column.comment.replace('\'', '"') + "'");
diff --git a/src/main/java/org/redkale/source/DataJdbcSource.java b/src/main/java/org/redkale/source/DataJdbcSource.java
index 14416f15d..525ee4181 100644
--- a/src/main/java/org/redkale/source/DataJdbcSource.java
+++ b/src/main/java/org/redkale/source/DataJdbcSource.java
@@ -135,7 +135,9 @@ public class DataJdbcSource extends AbstractDataSqlSource {
final List prestmts = new ArrayList<>();
for (Map.Entry> en : prepareInfos.entrySet()) {
PrepareInfo prepareInfo = en.getValue();
- PreparedStatement prestmt = conn.prepareUpdateStatement(prepareInfo.prepareSql);
+ PreparedStatement prestmt = info.isAutoGenerated()
+ ? conn.prepareUpdateStatement(prepareInfo.prepareSql, Statement.RETURN_GENERATED_KEYS)
+ : conn.prepareUpdateStatement(prepareInfo.prepareSql);
for (final T value : prepareInfo.entitys) {
bindStatementParameters(conn, prestmt, info, attrs, value);
prestmt.addBatch();
@@ -147,7 +149,9 @@ public class DataJdbcSource extends AbstractDataSqlSource {
protected PreparedStatement prepareInsertEntityStatement(SourceConnection conn, String sql, EntityInfo info, T... entitys) throws SQLException {
Attribute[] attrs = info.insertAttributes;
- final PreparedStatement prestmt = conn.prepareUpdateStatement(sql);
+ final PreparedStatement prestmt = info.isAutoGenerated()
+ ? conn.prepareUpdateStatement(sql, Statement.RETURN_GENERATED_KEYS)
+ : conn.prepareUpdateStatement(sql);
for (final T value : entitys) {
bindStatementParameters(conn, prestmt, info, attrs, value);
prestmt.addBatch();
@@ -341,6 +345,8 @@ public class DataJdbcSource extends AbstractDataSqlSource {
PreparedStatement prestmt = null;
List prestmts = null;
Map> prepareInfos = null;
+ final Attribute primary = info.getPrimary();
+ final Class primaryType = primary.type();
Attribute[] attrs = info.insertAttributes;
if (info.getTableStrategy() == null) { //单库单表
presql = info.getInsertQuestionPrepareSQL(entitys[0]);
@@ -352,6 +358,23 @@ public class DataJdbcSource extends AbstractDataSqlSource {
try {
if (info.getTableStrategy() == null) { //单库单表
c = Utility.sum(prestmt.executeBatch());
+ if (info.isAutoGenerated()) { //由数据库自动生成主键值
+ ResultSet set = prestmt.getGeneratedKeys();
+ int i = -1;
+ while (set.next()) {
+ T entity = entitys[++i];
+ if (primaryType == int.class || primaryType == Integer.class) {
+ primary.set(entity, set.getInt(1));
+ } else if (primaryType == long.class || primaryType == long.class) {
+ primary.set(entity, set.getLong(1));
+ } else if (primaryType == String.class) {
+ primary.set(entity, set.getString(1));
+ } else {
+ primary.set(entity, set.getObject(1));
+ }
+ }
+ set.close();
+ }
conn.offerUpdateStatement(prestmt);
} else { //分库分表
int c1 = 0;
@@ -359,6 +382,28 @@ public class DataJdbcSource extends AbstractDataSqlSource {
c1 += Utility.sum(stmt.executeBatch());
}
c = c1;
+ if (info.isAutoGenerated()) { //由数据库自动生成主键值
+ int j = -1;
+ for (Map.Entry> en : prepareInfos.entrySet()) {
+ PrepareInfo prepareInfo = en.getValue();
+ PreparedStatement stmt = prestmts.get(++j);
+ ResultSet set = stmt.getGeneratedKeys();
+ int i = -1;
+ while (set.next()) {
+ T entity = prepareInfo.entitys.get(++i);
+ if (primaryType == int.class || primaryType == Integer.class) {
+ primary.set(entity, set.getInt(1));
+ } else if (primaryType == long.class || primaryType == long.class) {
+ primary.set(entity, set.getLong(1));
+ } else if (primaryType == String.class) {
+ primary.set(entity, set.getString(1));
+ } else {
+ primary.set(entity, set.getObject(1));
+ }
+ }
+ set.close();
+ }
+ }
for (PreparedStatement stmt : prestmts) {
conn.offerUpdateStatement(stmt);
}
@@ -490,6 +535,23 @@ public class DataJdbcSource extends AbstractDataSqlSource {
conn.offerUpdateStatement(prestmt);
prestmt = prepareInsertEntityStatement(conn, presql, info, entitys);
c = Utility.sum(prestmt.executeBatch());
+ if (info.isAutoGenerated()) { //由数据库自动生成主键值
+ ResultSet set = prestmt.getGeneratedKeys();
+ int i = -1;
+ while (set.next()) {
+ T entity = entitys[++i];
+ if (primaryType == int.class || primaryType == Integer.class) {
+ primary.set(entity, set.getInt(1));
+ } else if (primaryType == long.class || primaryType == long.class) {
+ primary.set(entity, set.getLong(1));
+ } else if (primaryType == String.class) {
+ primary.set(entity, set.getString(1));
+ } else {
+ primary.set(entity, set.getObject(1));
+ }
+ }
+ set.close();
+ }
conn.offerUpdateStatement(prestmt);
} else { //分库分表
for (PreparedStatement stmt : prestmts) {
@@ -501,6 +563,28 @@ public class DataJdbcSource extends AbstractDataSqlSource {
c1 += Utility.sum(stmt.executeBatch());
}
c = c1;
+ if (info.isAutoGenerated()) { //由数据库自动生成主键值
+ int j = -1;
+ for (Map.Entry> en : prepareInfos.entrySet()) {
+ PrepareInfo prepareInfo = en.getValue();
+ PreparedStatement stmt = prestmts.get(++j);
+ ResultSet set = stmt.getGeneratedKeys();
+ int i = -1;
+ while (set.next()) {
+ T entity = prepareInfo.entitys.get(++i);
+ if (primaryType == int.class || primaryType == Integer.class) {
+ primary.set(entity, set.getInt(1));
+ } else if (primaryType == long.class || primaryType == long.class) {
+ primary.set(entity, set.getLong(1));
+ } else if (primaryType == String.class) {
+ primary.set(entity, set.getString(1));
+ } else {
+ primary.set(entity, set.getObject(1));
+ }
+ }
+ set.close();
+ }
+ }
for (PreparedStatement stmt : prestmts) {
conn.offerUpdateStatement(stmt);
}
@@ -2897,6 +2981,10 @@ public class DataJdbcSource extends AbstractDataSqlSource {
return conn.prepareStatement(sql);
}
+ public PreparedStatement prepareUpdateStatement(String sql, int resultSetType) throws SQLException {
+ return conn.prepareStatement(sql, resultSetType);
+ }
+
public void offerUpdateStatement(final PreparedStatement stmt) throws SQLException {
stmt.close();
}
diff --git a/src/main/java/org/redkale/source/DataSqlSource.java b/src/main/java/org/redkale/source/DataSqlSource.java
index 842f087c6..643ecf673 100644
--- a/src/main/java/org/redkale/source/DataSqlSource.java
+++ b/src/main/java/org/redkale/source/DataSqlSource.java
@@ -67,4 +67,11 @@ public interface DataSqlSource extends DataSource {
});
}
+ default Map executeQueryStrStrMap(String sql) {
+ return executeQueryMap(String.class, String.class, sql);
+ }
+
+ default Map executeQueryIntStrMap(String sql) {
+ return executeQueryMap(Integer.class, String.class, sql);
+ }
}
diff --git a/src/main/java/org/redkale/source/EntityInfo.java b/src/main/java/org/redkale/source/EntityInfo.java
index 2eca9c1c5..6696aa823 100644
--- a/src/main/java/org/redkale/source/EntityInfo.java
+++ b/src/main/java/org/redkale/source/EntityInfo.java
@@ -72,6 +72,9 @@ public final class EntityInfo {
//DDL字段
final EntityColumn[] primaryColumnOneArray;
+ //是否由数据库生成主键值
+ private final boolean autoGenerated;
+
//DDL字段集合
final EntityColumn[] ddlColumns;
@@ -381,6 +384,7 @@ public final class EntityInfo {
} catch (Exception e) {
logger.log(Level.SEVERE, type + " cannot find ConstructorParameters Creator", e);
}
+ boolean auto = false;
String[] constructorParameters = cps;
Attribute idAttr0 = null;
Map aliasmap = null;
@@ -431,9 +435,12 @@ public final class EntityInfo {
boolean idFlag = field.getAnnotation(Id.class) != null || field.getAnnotation(javax.persistence.Id.class) != null;
if (idFlag && idAttr0 == null) {
+ auto = field.getAnnotation(GeneratedValue.class) != null;
idAttr0 = attr;
- insertCols.add(sqlField);
- insertAttrs.add(attr);
+ if (!auto) {
+ insertCols.add(sqlField);
+ insertAttrs.add(attr);
+ }
RedkaleClassLoader.putReflectionField(cltmp.getName(), field);
} else {
if (col == null || col.insertable()) {
@@ -488,6 +495,7 @@ public final class EntityInfo {
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
this.jsonConvert = convert == null ? DEFAULT_JSON_CONVERT : convert;
+ this.autoGenerated = auto;
this.primary = idAttr0;
this.primaryOneArray = new Attribute[]{this.primary};
List ddls = new ArrayList<>();
@@ -777,6 +785,10 @@ public final class EntityInfo {
return table == null;
}
+ public boolean isAutoGenerated() {
+ return autoGenerated;
+ }
+
public DistributeTableStrategy getTableStrategy() {
return tableStrategy;
}