工厂模式的应用——SSM框架中DAO层工厂

    第一次写博客好激动,终于鼓足勇气迈出了第一步,有瑕疵的地方望大家批评指正。

    下面开始正文

    在SSM框架下用generate生成器会生成很多类似的方法。比如

public interface UsersDao {
    int deleteByPrimaryKey(Integer userId);

    int insert(Users users);

    int insertSelective(Users users);

    Users selectByPrimaryKey(Integer userId);

    int updateByPrimaryKeySelective(Users users);

    int updateByPrimaryKey(Users users);
    
}
    所有自动生成的DAO层都有这6个相同的方法。下面我们用工厂模式把这些DAO层管理起来,达到我们这样的目的通用的数据库“增,删,改,查”,就是根据我们传入工厂的参数,自动调用对应的DAO和DAO中的方法。做一个简单的例子。

    首先在数据库创建两个表 user表和city表

   

mysql> create table user(
    -> id INT NOT NULL AUTO_INCREMENT,
    -> name VARCHAR(100),
    -> password VARCHAR(100),
    -> PRIMARY KEY(id)
    -> );
Query OK, 0 rows affected (0.05 sec)
mysql> create table city(
    -> id INT NOT NULL AUTO_INCREMENT,
    -> city_name VARCHAR(100),
    -> city_code VARCHAR(100),
    -> PRIMARY KEY(id)
    -> );
Query OK, 0 rows affected (0.02 sec)

    插入几条测试用的数据

mysql> INSERT INTO user(name,password)
    -> VALUES('jack','111'),('rose','222');

mysql> INSERT INTO city(city_name,city_code)
    -> VALUES ('北京','100000'),('天津','120000');

接下来创建entiey

public class City {
	private Integer id;
	
	private String cityName;
	
	private String cityCode;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getCityName() {
		return cityName;
	}

	public void setCityName(String cityName) {
		this.cityName = cityName;
	}

	public String getCityCode() {
		return cityCode;
	}

	public void setCityCode(String cityCode) {
		this.cityCode = cityCode;
	}

	@Override
	public String toString() {
		return "City [id=" + id + ", cityName=" + cityName + ", cityCode=" + cityCode + "]";
	}
	
	
}

public class User {
	private String id;
	private String name;
	private String password;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public User(String name, String password) {
		super();
		this.name = name;
		this.password = password;
	}
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
	}
	
}

创建一个Dao文件(持久层)的父接口(这里的方法要写子接口共有的)

import java.util.List;

public interface Dao {
	Object  findByName(String name);
	List<Object> select(Object object);
}
和两个映射文件

import java.util.List;

public interface CityDao extends Dao{
	City  findByName(String name);
	List<City> select(City city);
}


import java.util.List;

public interface UserDao extends Dao{
	User  findByName(String name);
	List<User> select(User user);
}

两个都继承父接口DAO,然后写两个表的XML文件(映射文件)
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
 "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="cn.tedu.demo3.dao.UserDao">
	<select id="findByName"
			  parameterType="String"
			  resultType="cn.tedu.demo3.entity.User">
		select
			name as name,
			password as password 
		from user
		where name=#{name}
	</select>
	<select id="select" parameterType="cn.tedu.demo3.entity.User" resultType="cn.tedu.demo3.entity.User">
		select
			id id,
			name name,
			password password 
		from user
		<where>
			<if test="id != null">
				and id=#{id}
			</if>
			<if test="name != null">
				and name=#{name}
			</if>
			<if test="password != null">
				and password=#{password}
			</if>
		</where>
	</select>
</mapper>


<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
 "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="cn.tedu.demo3.dao.CityDao">
	<select id="findByName"
			  parameterType="String"
			  resultType="cn.tedu.demo3.entity.City">
		select
			id id,
			city_name cityName,
			city_code cityCode 
		from city
		where city_name=#{name}
	</select>
	<select id="select" parameterType="cn.tedu.demo3.entity.City" resultType="cn.tedu.demo3.entity.City">
		select
			id id,
			city_name cityName,
			city_code cityCode 
		from city
		<where>
			<if test="id != null">
				and id=#{id}
			</if>
			<if test="cityName != null">
				and city_name=#{cityName}
			</if>
			<if test="id != cityCode">
				and city_code=#{cityCode}
			</if>
		</where>
	</select>
</mapper>

写工厂类

package cn.tedu.demo3.util;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import cn.tedu.demo3.dao.CityDao;
import cn.tedu.demo3.dao.Dao;
import cn.tedu.demo3.dao.UserDao;
@Component
public class MapperFactory {
	
	@Resource
	private UserDao userDao;
	@Resource
	private CityDao cityDao;
	
	
	public CityDao getCityDao() {
		return cityDao;
	}


	public void setCityDao(CityDao cityDao) {
		this.cityDao = cityDao;
	}


	public UserDao getUserDao() {
		return userDao;
	}


	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	//这个方法比较局限,每增加一个DAO文件都要增加里边的逻辑
	public Dao getDao(String tableName,MapperFactory factory) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		if(tableName == null){
	         return null;
	      } 
		if(tableName.equalsIgnoreCase("user")){
	         return userDao;
	      }
		return null;
		//return (Dao)getObject(tableName,factory);
	}
	
	//这个方法比较通用,只需要注入DAO,加上get方法就行
	//这里是根据表名来拼接一个getter方法名,调用这个get方法获得对应的DAO
	//因为spring管理起来的dao接口都是单例的(只能存在一个)所以只能通过注解注入,
	//通过getter获得,不用new新的对象
	public Dao getObject(String tableName ,MapperFactory factory) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		String firstLetter = tableName.substring(0, 1).toUpperCase();    
		String getter = "get" + firstLetter + tableName.substring(1)+"Dao"; 
		Method method = factory.getClass().getMethod(getter, new Class[] {});
		Object value = method.invoke(factory, new Object[] {});    
        return (Dao)value;
	}
}
在业务层注入工厂类
@Resource
private MapperFactory factory;
封装一个通用的方法

/**
* @param tableName 表名
* @param object 对象(对象中set进去的就是搜索条件)
* @return 返回对象集合
*/
public List<Object> select(String tableName,Object object) throws Exception {
	Dao dao = factory.getObject(tableName,factory);
	List<Object> objectList = dao.select(object);
	return objectList;
}
到这就完了,可以测试一下试试了

/**
* 测试方法
*/
public void test() throws Exception {
	User user = new User();
	user.setName("jack");
	List<Object> list = select("user", user);
	for (Object object : list) {
		System.out.println(object);
	}
} 
打印结果

User [id=1, name=jack, password=111]
第二个测试方法

/**
* 测试方法
*/
public void test() throws Exception {
	//User user = new User();
	//user.setName("jack");
	List<Object> list = select("city", null);
	for (Object object : list) {
		System.out.println(object);
	}
}

打印结果
City [id=1, cityName=北京, cityCode=100000]
City [id=2, cityName=天津, cityCode=120000]
这个工厂模式扩展性不是很强,而且增加了理解和业务的难度,也就用起来比较方便
希望大神们能批评指正。谢谢CSDN里的前辈们让我学习到很多


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值