باستخدام حامل المفاتيح في الربيع مع المفاتيح الأولية التي تم إنشاؤها برمجيًا
-
26-09-2019 - |
سؤال
أنا أستخدم namedparameterjdbctemplate من الربيع لأداء إدراج في جدول. يستخدم الجدول NextVal على تسلسل للحصول على المفتاح الأساسي. ثم أريد أن يتم نقل هذا المعرف الذي تم إنشاؤه إلي. أنا أستخدم تطبيق حامل المفاتيح في الربيع مثل هذا:
KeyHolder key = new GeneratedKeyHolder();
jdbcTemplate.update(Constants.INSERT_ORDER_STATEMENT, params, key);
ومع ذلك ، عندما أقوم بتشغيل هذا البيان ، أحصل على:
org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:73)
أي أفكار ما أفتقده؟
المحلول
أعتقد أنك تستخدم الطريقة الخاطئة JdbcTemplate
. الوحيد من update
الطرق التي يبدو أنها تتطابق مع جزء الكود الخاص بك
int update(String sql, Object... args)
إذا كان الأمر كذلك ، فأنت تمر params
و key
كصفيف Vargs ثنائي العناصر ، و JdbcTemplate
يعالج key
كمعلمات ربط طبيعية ، وسوء تفسيرها.
الجمهور الوحيد update
طريقة على JdbcTemplate
هذا يأخذ KeyHolder
هو
int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
لذلك ستحتاج إلى إعادة صياغة الكود الخاص بك لاستخدام ذلك.
نصائح أخرى
فقط حل مشكلة مماثلة - مع Oracle تحتاج إلى استخدام طريقة أخرى (من NamedParameterJdbcOperations
) -
int update(String sql,
SqlParameterSource paramSource,
KeyHolder generatedKeyHolder,
String[] keyColumnNames)
throws DataAccessException
مع keycolumnnames تحتوي على أعمدة تم إنشاؤها تلقائيًا ، في حالتي فقط ["id"]. وإلا فإن كل ما تحصل عليه هو رويد. نرى وثيقة الربيع للتفاصيل.
عليك تنفيذ JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k)
.
سيتم حقن المفتاح الذي تم إرجاعه من قاعدة البيانات في KeyHolder
كائن المعلمة.
مثال:
final String INSERT_ORDER_STATEMENT
= "insert into order (product_id, quantity) values(?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(
Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(
INSERT_ORDER_STATEMENT, new String[] { "id" });
ps.setInt(1, order.getProductId());
ps.setInt(2, order.getQuantity());
return ps;
}
}, keyHolder);
يمكن العثور على مزيد من المعلومات هنا في الوثائق المرجعية.
لا يوجد تفصيلي على konstantin الإجابة: إليك مثال يعمل تمامًا: على افتراض أن قاعدة البيانات هي Oracle و Column Name التي يتم إنشاؤها معرف المتجر "enderated_id" (يمكن أن يكون أي اسم). ملاحظة: لقد استخدمت namedparameterjdbctemplate.update (....) في هذا المثال ، فئة JDBCtemplate من الربيع.
public Integer insertRecordReturnGeneratedId(final MyObject obj)
{
final String INSERT_QUERY = "INSERT INTO MY_TABLE VALUES(GENERATED_ID_SEQ.NEXTVAL, :param1, :param2)";
try
{
MapSqlParameterSource parameters = new MapSqlParameterSource().addValue( "param1", obj.getField1() ).addValue( "param2", obj.getField1() ) ;
final KeyHolder holder = new GeneratedKeyHolder();
this.namedParameterJdbcTemplate.update( INSERT_QUERY, parameters, holder, new String[] {"GENERATED_ID" } );
Number generatedId = holder.getKey();
// Note: USING holder.getKey("GENERATED_ID") IS ok TOO.
return generatedId.intValue();
}
catch( DataAccessException dataAccessException )
{
}
}
مع MySQL
CREATE TABLE `vets` (
`id` int(4) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(30) DEFAULT NULL,
`last_name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
public @Data class Vet {
private int id;
private String firstname;
private String lastname;
}
@Repository
public class VetDaoImpl implements VetDao {
/** Logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(VetDaoImpl.class);
private static final String INSERT_VET = "INSERT INTO vets (first_name, last_name) VALUES (:first_name, :last_name)";
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Override
public Number insertVet(final Vet vet) {
MapSqlParameterSource paramSource = new MapSqlParameterSource();
paramSource.addValue("first_name", vet.getFirstname());
paramSource.addValue("last_name", vet.getLastname());
KeyHolder keyHolder = new GeneratedKeyHolder();
int nbRecord = namedParameterJdbcTemplate.update(INSERT_VET, paramSource, keyHolder, new String[] {"id" });
LOGGER.info("insertVet: id ["+keyHolder.getKey()+"]");
return nbRecord;
}
}