JdbcTemplate – JDBC asosiy paketidagi markaziy klassi. Bu resurslarni yaratish va ozod qilishni boshqaradi, bu odatda ulanishni yopishni unutish kabi keng tarqalgan xatolardan qochishga yordam beradi. Bu JDBC asosiy ish jarayonidagi asosiy vazifalarni bajaradi (masalan, buyruqlar yaratish va bajarish), dasturning kodiga SQL ni taqdim etish va natijalarni chiqazishni qoldiradi. JdbcTemplate klassi:
-
SQL-so'rovlarni bajaradi
-
Statementlarni va saqlangan proseduralarni yangilaydi
-
ResultSetnamunalari bo'yicha iteratsiya va qaytarilgan parametr qiymatlarini olishni amalga oshiradi. -
JDBC istisnolarini ushlab qoladi va ularni
org.springframework.daopaketida aniqlangan, turlangan, ko'proq ma'lumot beruvchi istisnolar iyerarxiyasiga aylantiradi. (Qo'shimcha ma'lumot uchun Kelishilgan istisnolar iyerarxiyasini ko'ring).
Agar siz шаблон JdbcTemplate shablonini kodingizda ishlatsangiz, qayta qo'ng'iroq qilish interfeyslarini amalga oshirish va ularga aniq belgilangan shartnoma berish kifoya qiladi. JdbcTemplate klassi tomonidan taqdim etilgan Connectionni hisobga olmagan holda, PreparedStatementCreator interfeysi SQL va barcha zarur parametrlarning taqdim etilishi bilan tayyorlangan statementni yaratadi. Xuddi shu usul CallableStatementCreator interfeysiga ham tegishli, u chaqiriladigan instruktsiyalarni yaratadi. RowCallbackHandler interfeysi ResultSetning har bir qatoridan qiymatlarni oladi.
DAOni amalga oshirishda JdbcTemplatedan foydalanishingiz mumkin, bu DataSourcega havola bilan bevosita yaratish orqali amalga oshiriladi yoki uni Spring IoC-konteynerida konfiguratsiya qilib, DAOga bean havola sifatida uzatish orqali.
DataSource doimo Spring IoC-konteynerida bean sifatida konfiguratsiya qilinishi kerak. Birinchi holatda bean to'g'ridan-to'g'ri xizmatga uzatiladi; ikkinchi holatda esa tayyorlangan shablon orqali uzatiladi.
Bu klass tomonidan chiqarilgan barcha SQL DEBUG darajasida, shablon nusxasi klassining to'liq nomiga mos keladigan kategoriyada ro'yxatga olinadi (odatda JdbcTemplate, lekin agar siz JdbcTemplate klassining maxsus subclassini ishlatsangiz, o'zgarishi mumkin).
Quyidagi bo'limlarda JdbcTemplate dan foydalanishning ba'zi misollari keltirilgan. Bu misollar JdbcTemplate tomonidan taqdim etilgan barcha imkoniyatlarning to'liq ro'yxati emas. Qo'shimcha ma'lumotni ilova qilingan javadoc da ko'ring.
So'rovlar yaratish (SELECT)
Quyidagi so'rov nisbatan satrlar sonini olish imkonini beradi:
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);
val rowCount = jdbcTemplate.queryForObject<Int>("select count(*) from t_actor")!!
Quyidagi so'rovda bog'lanish o'zgaruvchisi ishlatiladi:
int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject(
"select count(*) from t_actor where first_name = ?", Integer.class, "Joe");
val countOfActorsNamedJoe = jdbcTemplate.queryForObject<Int>(
"select count(*) from t_actor where first_name = ?", arrayOf("Joe"))!!
Quyidagi so'rov Stringni qidiradi:
String lastName = this.jdbcTemplate.queryForObject(
"select last_name from t_actor where id = ?",
String.class, 1212L);
val lastName = this.jdbcTemplate.queryForObject<String>(
"select last_name from t_actor where id = ?",
arrayOf(1212L))!!
Quyidagi so'rov bir ob'ektni topib to'ldiradi:
Actor actor = jdbcTemplate.queryForObject(
"select first_name, last_name from t_actor where id = ?",
(resultSet, rowNum) -> {
Actor newActor = new Actor();
newActor.setFirstName(resultSet.getString("first_name"));
newActor.setLastName(resultSet.getString("last_name"));
return newActor;
},
1212L);
val actor = jdbcTemplate.queryForObject(
"select first_name, last_name from t_actor where id = ?",
arrayOf(1212L)) { rs, _ ->
Actor(rs.getString("first_name"), rs.getString("last_name"))
}
Quyidagi so'rov bir ro'yxatni topib to'ldiradi:
List<Actor> actors = this.jdbcTemplate.query(
"select first_name, last_name from t_actor",
(resultSet, rowNum) -> {
Actor actor = new Actor();
actor.setFirstName(resultSet.getString("first_name"));
actor.setLastName(resultSet.getString("last_name"));
return actor;
});
val actors = jdbcTemplate.query("select first_name, last_name from t_actor") { rs, _ ->
Actor(rs.getString("first_name"), rs.getString("last_name"))
Agar oxirgi ikki kod parchalari haqiqatan ham bir dasturda bo'lganida, ikkita RowMapper lamba ifodalarida mavjud bo'lgan takrorlanishni olib tashlash va ularni qachon kerak bo'lsa DAO metodlariga murojaat qilishi mumkin bo'lgan bitta maydonga chiqarish mantiqan bo'lardi. Masalan, oldingi kod parchasi quyidagi tarzda yaxshiroq yoziladi:
private final RowMapper<Actor> actorRowMapper = (resultSet, rowNum) -> {
Actor actor = new Actor();
actor.setFirstName(resultSet.getString("first_name"));
actor.setLastName(resultSet.getString("last_name"));
return actor;
};
public List<Actor> findAllActors() {
return this.jdbcTemplate.query("select first_name, last_name from t_actor", actorRowMapper);
}
val actorMapper = RowMapper<Actor> { rs: ResultSet, rowNum: Int ->
Actor(rs.getString("first_name"), rs.getString("last_name"))
}
fun findAllActors(): List<Actor> {
return jdbcTemplate.query("select first_name, last_name from t_actor", actorMapper)
}
Yangilash (INSERT, UPDATE va DELETE) yordamida JdbcTemplate
Siz update(..) metodidan foydalanib qo'shish, yangilash va o'chirish operatsiyalarini bajarishingiz mumkin. Parametr qiymatlari odatda o'zgaruvchi argumentlari sifatida yoki boshqa varianti, obyektlar arrayi sifatida taqdim etiladi.
Quyidagi misolda yangi yozuv qo'shiladi:
this.jdbcTemplate.update(
"insert into t_actor (first_name, last_name) values (?, ?)",
"Leonor", "Watling");
jdbcTemplate.update(
"insert into t_actor (first_name, last_name) values (?, ?)",
"Leonor", "Watling")
Quyidagi misolda mavjud yozuv yangilanadi:
this.jdbcTemplate.update(
"update t_actor set last_name = ? where id = ?",
"Banjo", 5276L);
jdbcTemplate.update(
"update t_actor set last_name = ? where id = ?",
"Banjo", 5276L)
Quyidagi misolda yozuv o'chiriladi:
this.jdbcTemplate.update(
"delete from t_actor where id = ?",
Long.valueOf(actorId));
jdbcTemplate.update("delete from t_actor where id = ?", actorId.toLong())
Boshqa JdbcTemplate operatsiyalari
Metod execute(..) dan foydalanib ixtiyoriy SQL ni bajarishingiz mumkin. Shuning uchun, bu metod ko'pincha ma'lumotlar ta'rifi tili (Data Definition Language /DDL) buyruqlari uchun ishlatiladi. Bu juda ko'p yuklangan variantlar, chunki interfeys qayta chaqiruvi, bog'langan arraylar va boshqalarni qabul qiladi. Quyidagi misolda jadval yaratiladi:
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
jdbcTemplate.execute("create table mytable (id integer, name varchar(100))")
Quyidagi misolda saqlangan protsedura chaqiriladi:
this.jdbcTemplate.update(
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
Long.valueOf(unionId));
jdbcTemplate.update(
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
unionId.toLong())
Saqlangan proseduralarning ilg'or qo'llab-quvvatlashi kelsa ko'rib chiqiladi.
JdbcTemplate bilan ishning optimal usullari
Konfiguratsiya tugagach, JdbcTemplate klassining nusxalari ipdan xavfsizdir. Bu muhim, chunki bu bitta JdbcTemplate nusxasini konfiguratsiya qilishingiz va keyinchalik bu umumiy havolani bir necha DAO (yoki reppozitoriy) ga xavfsiz kiritishingiz mumkinligini anglatadi. JdbcTemplate holatni saqlaydi, chunki u DataSourcega havolani saqlaydi, lekin bu holat dialog holati emas.
Optimal ish usuli JdbcTemplate klassidan foydalangan holda (va unga tegishli NamedParameterJdbcTemplate klassi) DataSourceni Spring konfiguratsiya faylida konfiguratsiya qilish va keyin bu umumiy DataSource beaniga bo'lgan qaramlikni DAO klasslariga kiritishdir. JdbcTemplate DataSource uchun ko'rsatkichda yaratiladi. Bu taxminan quyidagi ko'rinishdagi DAOga olib keladi:
public class JdbcCorporateEventDao implements CorporateEventDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// JDBC qo'llab-quvvatlaydigan CorporateEventDao metodlarining amalga oshirishlari keladi...
}
class JdbcCorporateEventDao(dataSource: DataSource) : CorporateEventDao {
private val jdbcTemplate = JdbcTemplate(dataSource)
// JDBC qo'llab-quvvatlaydigan CorporateEventDao metodlarining amalga oshirishlari keladi...
}
Quyidagi misolda mos XML-konfiguratsiya keltirilgan:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties"/>
</beans>
Aniq konfiguratsiya alternativasi komponentlarni skanerlash va qaramlikni kiritish uchun annotatsiyalarni qo'llab-quvvatlashdan foydalanishdir. Bu holda siz sinfni @Repository annotatsiyasi bilan belgilashingiz (bu uni komponentlarni skanerlash uchun nomzod qiladi) va DataSourceni o'rnatish metodini @Autowired annotatsiyasi bilan belgilashingiz mumkin. Quyidagi misolda qanday qilinishini ko'rsatadi:
@Repository
public class JdbcCorporateEventDao implements CorporateEventDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// JDBC qo'llab-quvvatlaydigan CorporateEventDao metodlarining amalga oshirishlari keladi...
}
- Sinfni
@Repositorybilan annotatsiya qilamiz. - Setter
DataSourceni@Autowiredbilan annotatsiya qilamiz. - Yangi
JdbcTemplateniDataSourceni ishlatib yaratamiz.
@Repository
class JdbcCorporateEventDao(dataSource: DataSource) : CorporateEventDao {
private val jdbcTemplate = JdbcTemplate(dataSource)
// JDBC qo'llab-quvvatlaydigan CorporateEventDao metodlarining amalga oshirishlari keladi...
}
- Sinfni
@Repositorybilan annotatsiya qilamiz. - Constructor injection of the
DataSource. - Yangi
JdbcTemplateniDataSourceni ishlatib yaratamiz.
Quyidagi misolda mos XML-konfiguratsiya keltirilgan:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Asosiy paketdagi @Component annotatsiyasi bilan sinflarni skanerlash va ularni bean sifatida konfiguratsiya qilish -->
<context:component-scan base-package="org.springframework.docs.test" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties"/>
</beans>
Agar siz Springdan JdbcDaoSupport klassidan foydalanayotgan bo'lsangiz, va turli DAO klasslari unga yaqin bo'lsa, sizning subclassingiz JdbcDaoSupport klassidan setDataSource(..) metodini meros oladi. Siz bu klassdan meros olishingiz yoki olmasligingiz mumkin. JdbcDaoSupport klassi faqat qulaylik uchun mavjud.
Yuqorida aytib o'tilgan shablonni initsializatsiya qilish uslubidan (yoki ishlatmaslikdan) qaysi biri siz tanlasangiz ham, bu vaqtda SQLni har safar bajarishingiz kerak bo'lganida yangi JdbcTemplate nusxasini yaratish zarur bo'lmaydi. Konfiguratsiya tugagach, bir JdbcTemplate nusxasi ipdan xavfsiz bo'ladi. Agar sizning ilovangiz bir nechta ma'lumotlar bazasiga murojaat qilsa, sizga bir nechta JdbcTemplate nusxalari kerak bo'lishi mumkin, bu bir nechta DataSourcesga va shunga mos ravishda bir nechta turli konfiguratsiyalangan JdbcTemplate nusxalariga ehtiyoj qiladi.
GO TO FULL VERSION