在Java WEB的DAO层开发中关于DAO接口的使用,求解答
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Java WEB的DAO层开发中关于DAO接口的使用,求解答相关的知识,希望对你有一定的参考价值。
在JavaWEB开发中,很多人喜欢使用DAO接口,然后不同的数据表DAO都实现该接口,但是不同的dao类,对数据的处理方法也不尽相同,那接口有什么用呢?
接口是为了屏蔽不同数据库的JDBC实现差异而出现的。以常见的系统组织结构为例,管理系统里有一个部门department表用于存放部门信息,因为部门下面可能有子部门所以表中的字段要定义成类似树形结构的方式(parentId呀什么的)。这时我们想在java中用sql去查询指定部门下的数据,你就要考虑不同数据库的SQL语句的问题了:Oracle sql提供了树查询的方法,你只需要发一句sql就能查询出该部门下的所有子部门信息;但是mysql就不行,mysql就只能通过java递归一条一条查询。那么假如我们的系统即要支持Oracle又要支持mysql,这时我们查询部门怎么办呢?这时就要考虑接口,看下面的代码:
首先定义一个部门接口,该接口有一个findDept方法用于查询部门下的所有子部门
Interface DepartmentDao
//根据父部门ID查询部门下的所有子部门
public List findDept(int deptId);
有了接口,我们就需要有实现类了,这时我们为了考虑兼容性就需要编写两套接口类,一个是用mysql语句实现的类,另一个是用Oracle实现的类:
class MySqlDepartmentDaoImpl implement DepartmentDao
//根据父部门ID查询部门下的所有子部门
public List findDept(int deptId)String sql="mysql的sql语句".....
class OracleDepartmentDaoImpl implement DepartmentDao
//根据父部门ID查询部门下的所有子部门
public List findDept(int deptId)String sql="Oracle的sql语句".....
一个Dao工厂,这个工厂返回部门Dao接口的实例
class DaoFactory
public DepartmentDao getDepartmentDao()
if(使用的是Mysql数据库)
return new MySqlDepartmentDaoImpl ();
else
return new OracleDepartmentDaoImpl ();
上面的编码DaoFactory是关键,通过这个这个工厂只返回给我们接口实例,这样就屏蔽了不同数据库的差异性(如果用户使用的是mysql数据库就会返回new MySqlDepartmentDaoImpl ()反之为new OracleDepartmentDaoImpl ())。我们在编码中只需要通过DepartmentDao deptDao = DaoFactory.getDepartmentDao();deptDao.findDept就可以查询我们需要的数据了。
所以面向接口编程是很重要的东西,建议你学习一下spring的IOC,代码写多了你就明白接口的重要性了追问
你说的这个例子,我倒是明白,也很经典,但是举个例子:UserDao有个getUsersByClass()根据班级查询学生,ScoreDao里有个getUsersByScore()根据成绩查询学生列表,两个方法肯定不一样,也肯定不是公共的方法,在BaseDao接口里肯定不会有该方法的声明在使用该方法时:
UserDao dao = new UserDao()
dao.getUsersByClass()
而不是
BaseDao dao = new UserDao()
我大概猜想你的UserDao是这样的格式:class UserDao implement BaseDao,而getUsersByClass方法是在UserDao类中新建的一个方法,所以你在BaseDao中是找不到这个方法的。这里一定要注意:不推荐直接在类里创建public类型的方法,推荐在接口中定义public方法然后实现类去重写它即可。
注意实现类是可以继承多个接口的你可以定义一个接口UserInterface里面定义一个getUsersByClass方法,然后UserDao的代码改成class UserDao implement BaseDao,UserInterface,这时你就可以UserInterface userDao = new UserDao();userDao.getUsersByClass()
比如说,hibernate可以连接数据库,自己手写的JDBC也同样可以实现连接数据库。
当他们都实现了一个相同的接口,你的项目中只有转型为接口类型,你就不用管module层是怎样
去连接数据库的。
这个就是DAO接口的好处,也是接口的好处。
依赖注入的实现方式:设值注入和构造方法注入
SSH开发时,一般将项目分成3层:web层、service层和dao层。开发的基本流程是先定义dao接口,然后实现该接口,在定义同类型的service接口,再实现service接口(此时使用dao接口注入),接着再从web层去调用service层。
dao层完成的是底层的数据库操作,service层则完成纯粹的业务逻辑,该层中的数据操作部分是通过注入的dao层来实现的。service层的作用是将从dao层取得的数据做更贴近业务的实现,dao层则只实现对数据的增、删、改、查操作。使用这种分层方式更有利于项目的扩展和维护。
一、设值注入
设值注入是指IoC容器使用setter方法注入被依赖的实例。通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现基于setter的DI。
- 新建项目,配置运行环境(Build Path中加入spring和其它依赖的jar包)
- User类,作为被保存的模型对象
package com.deciphering.model; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
- User类的接口UserDAO(针对接口编程的好处是UserDAO可以有多个不同的实现类,分别用来操作不同的数据库)
package com.deciphering.dao; import com.deciphering.model.User; public interface UserDAO { public void save(User user); }
- UserDAO的实现类UserDAOImpl(简化处理)
package com.deciphering.dao.impl; import com.deciphering.dao.UserDAO; import com.deciphering.model.User; public class UserDAOImpl implements UserDAO { public void save(User user) { System.out.println(user.getUsername() + " saved in Oracle!"); //System.out.println(user.getUsername() + " saved in DB2!"); //System.out.println(user.getUsername() + " saved in mysql!"); } }
- 业务逻辑接口UserService
package com.deciphering.service; import com.deciphering.dao.UserDAO; import com.deciphering.model.User; public class UserServiceImpl { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } /* public UserServiceImpl(UserDAO userDAO) { super(); this.userDAO = userDAO; } */ }
- 业务逻辑接口的实现类UserServiceImpl
package com.deciphering.service; import com.deciphering.dao.UserDAO; import com.deciphering.model.User; public class UserServiceImpl implements UserService{ private UserDAO userDAO; public void add(User user){ userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
- Spring的配置文件beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="u" class="com.deciphering.dao.impl.UserDAOImpl"> </bean> <bean id="userService" class="com.deciphering.service.UserServiceImpl"> <property name="userDAO"> <ref bean="u"/> </property> </bean> </beans>
- 测试类
Test
package com.deciphering.service; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.deciphering.model.User; import com.deciphering.service.UserServiceImpl; public class UserServiceTest { @Test public void testAdd() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserServiceImpl service = (UserServiceImpl)ctx.getBean("userService"); User u = new User(); u.setUsername("测试用户"); u.setPassword("123456"); service.add(u); } }
二、构造方法注入
构造方法注入是指IoC容器使用构造方法来注入被依赖的实例。基于构造器的DI通过调用带参数的构造方法来实现,每个参数代表着一个依赖。
在上面的项目文件里,做少量的修改,即可变为构造方法注入。
- 修改UserServiceImpl类,在使用构造方法注入时,必须显式的给出待参数的构造方法。
package com.deciphering.service; import com.deciphering.dao.UserDAO; import com.deciphering.model.User; public class UserServiceImpl { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } //定义构造方法 public UserServiceImpl(UserDAO userDAO) { super(); this.userDAO = userDAO; } }
- 修改beans.xml文件,加粗代码为修改部分
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="u" class="com.deciphering.dao.impl.UserDAOImpl"> </bean> <bean id="userService" class="com.deciphering.service.UserServiceImpl"> <!-- <property name="userDAO"> <ref bean="u"/> </property> --> //使用构造方法注入,为UserService实例注入u实例 <constructor-arg> <ref bean="u"/> </constructor-arg> </bean> </beans>
文件结构:
以上是关于在Java WEB的DAO层开发中关于DAO接口的使用,求解答的主要内容,如果未能解决你的问题,请参考以下文章
java web项目中dao的接口,实现类和service接口,实现类区别
java开发时为啥要dao和service都是model层吗?
java web项目DAO层通用接口BaseDao与实现类BaseDaoImpl