Spring数据库访问之iBatis(二)
程序员文章站
2022-03-02 11:15:30
...
接上文,我们继续来研究Spring和iBatis的整合访问数据。下面首先来看看插入操作,数据的插入操作属于更新操作的一种,是比较简单的一种操作,就是将符合数据表字段规范且对应用程序无害的数据插入到数据表中。
我们分两种方式来进行插入操作,第一种是Bean的方式进行,首先来编写iBatis的插入SQL语句:
我们使用<insert>标签表示插入语句,为该语句起个名字,就是id属性中的insertContact,之后声明我们使用的参数类型,也就是我们声明过的Contact。需要注意的是这里的参数设置,#name:VARCHAR#,小写的name是Bean中的字段名称,大小写要完全一致才行,VARCHAR表示的是数据类型,不用多说。在数据表中的这四个字段我们都声明为VARCHAR类型,而插入时不需要设置ID,是因为我们使用MySQL数据库的自增主键了,如果是其它类型的数据库,请使用相应的主键生成策略来为主键赋值。
编写完SQL语句,我们来写DAO:
我们多加了一个insertContact(Contact contact)方法,返回值类型是int,也就是更新的行数,这都是JDBC规范中的内容,下面来实现这个新加的方法:
该方法的实现也非常简单,但是注意这里,我们并没有使用sqlMapClientTemplate的insert方法,而是update方法来进行操作的。原因是insert方法不会返回int类型的结果,而insert也是更新操作的一种,使用update方法也是可以的。下面在Service类中对应添加代码:
之后我们开始编写测试类,代码如下:
这里需要注意,我们创建Bean时使用了带有参数的构造方法(且不含ID),那么还需要在Contact类中声明出无参数的构造方法,也就是在Contact类中添加如下两个构造方法:
运行测试程序,我们会得到如下输出:
可以看出update语句的返回值是1,也就是说我们成功地更新了一行数据,打开数据表,我们可以看到这条数据已经成功添加进去了:
下面来看第二种参数设置方式,就是使用我们之前的ParameterMap方式。使用Bean是ORM特性的体现,而如果在一个事务中,需要向多个表中插入数据,显然使用Bean的方式存在不足,因为中间表可能没有对应的Bean存在,而且构造Bean是消耗系统资源的,特别是在批量操作时,是不建议使用Bean的方式的。那么我们可以使用ParameterMap的方式来统一设置传入参数。
修改SQL语句:
之后在DAO中重载一个insertContact方法:
然后编写实现代码:
和之前的完全类似,只是参数不同,就是重载了一个方法而已。下面是Service方法:
这里我们将传入的四个参数重新构造成一个ParameterMap类型的变量,为什么要在Service中完成这步操作,就是出于事务捆绑的操作。在Service层我们将操作视为一个具体的业务,那么它可能向下要调用多个DAO来向不同数据表进行操作,那么在这层构造数据调用各自的DAO完成SQL操作是最合理的,所以我们将数据的构造操作放在了Service层来进行,之后重新改写测试代码:
我们仍然得到了更新一行数据的结果,可以看到数据库中就又多了一条数据。
下面是数据更新操作,也就是SQL的update操作,还是先来编写SQL语句:
可以看出,这里也是使用Bean的方式来进行更新,那么DAO代码如下:
然后是Service代码:
而测试时,我们是先将一条记录给查出来,之后更改几个属性,再给更新数据,那么测试代码为:
运行测试代码,我们得到如下结果:
之后查看数据库,发现ID为2的记录已经更改了:
和插入操作一样,我们还可以使用ParameterMap的方式来实现更新,应用场景也是和前面类似的。这里就不再给出演示了,直接看最后一个操作,就是删除操作。删除应该是最简单的一种操作了,我们编写一个SQL:
我们使用的是parameterMap作为传入的参数类型,那么DAO代码如下:
在Service中,我们构造出parameerMap对象:
下面是测试代码,我们直接指定要删除的记录ID即可:
运行测试代码,我们可以看到成功更新了一条记录,也就是将第三条记录删除,那么再看看数据库,也就只有两条记录了。
本部分内容也就全部介绍完了。
我们分两种方式来进行插入操作,第一种是Bean的方式进行,首先来编写iBatis的插入SQL语句:
<insert id="insertContact" parameterClass="contact"> insert into contact(NAME,GENDER,MOBILE,ADDRESS) values (#name:VARCHAR#,#gender:VARCHAR#,#mobile:VARCHAR#,#address:VARCHAR#) </insert>
我们使用<insert>标签表示插入语句,为该语句起个名字,就是id属性中的insertContact,之后声明我们使用的参数类型,也就是我们声明过的Contact。需要注意的是这里的参数设置,#name:VARCHAR#,小写的name是Bean中的字段名称,大小写要完全一致才行,VARCHAR表示的是数据类型,不用多说。在数据表中的这四个字段我们都声明为VARCHAR类型,而插入时不需要设置ID,是因为我们使用MySQL数据库的自增主键了,如果是其它类型的数据库,请使用相应的主键生成策略来为主键赋值。
编写完SQL语句,我们来写DAO:
package org.ourpioneer.contact.dao; import java.util.Map; import org.ourpioneer.contact.bean.Contact; public interface ContactDAO { public Contact getContactById(Map<Object, Object> parameterMap); public int insertContact(Contact contact); }
我们多加了一个insertContact(Contact contact)方法,返回值类型是int,也就是更新的行数,这都是JDBC规范中的内容,下面来实现这个新加的方法:
package org.ourpioneer.contact.dao.impl; import java.util.Map; import org.ourpioneer.contact.bean.Contact; import org.ourpioneer.contact.common.BaseDAO; import org.ourpioneer.contact.dao.ContactDAO; public class ContactDAOImpl extends BaseDAO implements ContactDAO { public Contact getContactById(Map<Object, Object> parameterMap) { return (Contact) getSqlMapClientTemplate().queryForObject( "getContactById", parameterMap); } public int insertContact(Contact contact) { return getSqlMapClientTemplate().update("insertContact", contact); } }
该方法的实现也非常简单,但是注意这里,我们并没有使用sqlMapClientTemplate的insert方法,而是update方法来进行操作的。原因是insert方法不会返回int类型的结果,而insert也是更新操作的一种,使用update方法也是可以的。下面在Service类中对应添加代码:
public int insertContact(Contact contact) { return getContactDAO().insertContact(contact); }
之后我们开始编写测试类,代码如下:
package org.ourpioneer.contact; import org.ourpioneer.contact.bean.Contact; import org.ourpioneer.contact.service.ContactService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml"); ContactService contactService = (ContactService) context .getBean("contactService"); // Contact contact = contactService.getContactById(1); Contact contact = new Contact("Tom", "male", "15940990001", "Dalian"); int recordsOfUpdates = contactService.insertContact(contact); logger.info("{}", recordsOfUpdates); } }
这里需要注意,我们创建Bean时使用了带有参数的构造方法(且不含ID),那么还需要在Contact类中声明出无参数的构造方法,也就是在Contact类中添加如下两个构造方法:
public Contact() { super(); } public Contact(String name, String gender, String mobile, String address) { super(); this.name = name; this.gender = gender; this.mobile = mobile; this.address = address; }
运行测试程序,我们会得到如下输出:
可以看出update语句的返回值是1,也就是说我们成功地更新了一行数据,打开数据表,我们可以看到这条数据已经成功添加进去了:
下面来看第二种参数设置方式,就是使用我们之前的ParameterMap方式。使用Bean是ORM特性的体现,而如果在一个事务中,需要向多个表中插入数据,显然使用Bean的方式存在不足,因为中间表可能没有对应的Bean存在,而且构造Bean是消耗系统资源的,特别是在批量操作时,是不建议使用Bean的方式的。那么我们可以使用ParameterMap的方式来统一设置传入参数。
修改SQL语句:
<insert id="insertContact" parameterClass="parameterMap"> insert into contact(NAME,GENDER,MOBILE,ADDRESS) values (#NAME:VARCHAR#,#GENDER:VARCHAR#,#MOBILE:VARCHAR#,#ADDRESS:VARCHAR#) </insert>
之后在DAO中重载一个insertContact方法:
package org.ourpioneer.contact.dao; import java.util.Map; import org.ourpioneer.contact.bean.Contact; public interface ContactDAO { public Contact getContactById(Map<Object, Object> parameterMap); public int insertContact(Contact contact); public int insertContact(Map<Object, Object> parameterMap); }
然后编写实现代码:
public int insertContact(Map<Object, Object> parameterMap) { return getSqlMapClientTemplate().update("insertContact", parameterMap); }
和之前的完全类似,只是参数不同,就是重载了一个方法而已。下面是Service方法:
public int insertContact(String name, String gender, String mobile, String address) { Map<Object, Object> parameterMap = new ParameterMap("NAME", name, "GENDER", gender, "MOBILE", mobile, "ADDRESS", address); return getContactDAO().insertContact(parameterMap); }
这里我们将传入的四个参数重新构造成一个ParameterMap类型的变量,为什么要在Service中完成这步操作,就是出于事务捆绑的操作。在Service层我们将操作视为一个具体的业务,那么它可能向下要调用多个DAO来向不同数据表进行操作,那么在这层构造数据调用各自的DAO完成SQL操作是最合理的,所以我们将数据的构造操作放在了Service层来进行,之后重新改写测试代码:
package org.ourpioneer.contact; import org.ourpioneer.contact.service.ContactService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml"); ContactService contactService = (ContactService) context .getBean("contactService"); // Contact contact = contactService.getContactById(1); // Contact contact = new Contact("Tom", "male", "15940990001", // "Dalian"); int recordsOfUpdates = contactService.insertContact("Tom", "male","15940990001", "Dalian"); logger.info("{}", recordsOfUpdates); } }
我们仍然得到了更新一行数据的结果,可以看到数据库中就又多了一条数据。
下面是数据更新操作,也就是SQL的update操作,还是先来编写SQL语句:
<update id="updateContactById" parameterClass="contact"> update contact set NAME=#name:VARCHAR#,GENDER=#gender:VARCHAR#,MOBILE=#mobile:VARCHAR#,ADDRESS=#address:VARCHAR# where ID=#id:LONG# </update>
可以看出,这里也是使用Bean的方式来进行更新,那么DAO代码如下:
public int updateContactById(Contact contact) { return getSqlMapClientTemplate().update("updateContactById", contact); }
然后是Service代码:
public int updateContact(Contact contact) { return getContactDAO().updateContactById(contact); }
而测试时,我们是先将一条记录给查出来,之后更改几个属性,再给更新数据,那么测试代码为:
public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml"); ContactService contactService = (ContactService) context .getBean("contactService"); Contact contact = contactService.getContactById(2); System.out.println(contact); contact.setMobile("15900000001"); contact.setAddress("Beijing"); int recordsOfUpdates = contactService.updateContact(contact); logger.info("{}", recordsOfUpdates); }
运行测试代码,我们得到如下结果:
之后查看数据库,发现ID为2的记录已经更改了:
和插入操作一样,我们还可以使用ParameterMap的方式来实现更新,应用场景也是和前面类似的。这里就不再给出演示了,直接看最后一个操作,就是删除操作。删除应该是最简单的一种操作了,我们编写一个SQL:
<delete id="deleteContactById" parameterClass="parameterMap"> delete from contact where ID=#ID:LONG# </delete>
我们使用的是parameterMap作为传入的参数类型,那么DAO代码如下:
public int deleteContactById(Map<Object, Object> parameterMap) { return getSqlMapClientTemplate().update("deleteContactById", parameterMap); }
在Service中,我们构造出parameerMap对象:
public int deleteContactById(long id) { Map<Object, Object> parameterMap = new ParameterMap("ID", id); return getContactDAO().deleteContactById(parameterMap); }
下面是测试代码,我们直接指定要删除的记录ID即可:
public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml"); ContactService contactService = (ContactService) context .getBean("contactService"); int recordsOfUpdates = contactService.deleteContactById(3); logger.info("{}", recordsOfUpdates); } }
运行测试代码,我们可以看到成功更新了一条记录,也就是将第三条记录删除,那么再看看数据库,也就只有两条记录了。
本部分内容也就全部介绍完了。
推荐阅读
-
Spring Boot实战之数据库操作的示例代码
-
Spring之借助Redis设计一个简单访问计数器的示例
-
Spring Boot实战之数据库操作的示例代码
-
《解剖PetShop》之二:PetShop数据访问层数之据库访问设计
-
Spring boot 使用JdbcTemplate访问数据库
-
Spring boot中使用Spring-data-jpa方便快捷的访问数据库(推荐)
-
Node.js数据库操作之查询MySQL数据库(二)
-
Spring boot 使用JdbcTemplate访问数据库
-
《解剖PetShop》之二:PetShop数据访问层数之据库访问设计
-
Spring boot中使用Spring-data-jpa方便快捷的访问数据库(推荐)