Dao模型设计(基于Dao与Hebernate框架)

以前没有Dao设计模型之前,一般都是这样的流程:

①先设计实体对象

学生对象:

package com.itheima.domain;

import java.io.Serializable;
import java.util.Date;

public class Student implements Serializable {
	private Integer id;//可以为null
	private String name;
	private Date birthday;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", birthday="
				+ birthday + "]";
	}
}

客户对象:

package com.itheima.domain;

import java.io.Serializable;

public class Customer implements Serializable {
	private Integer id;
	private String name;
	private String gender;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", gender=" + gender
				+ "]";
	}
}

②设计Dao层

学生Dao

客户Dao

③Dao实现

学生Dao实现

客户Dao实现类似

可以发现,这样Dao多起来后,有很多的重复代码,主要集中在增删改查4个方法上面.


改进

一.在Dao包中,添加一个Dao接口

package com.itheima.dao;

import java.io.Serializable;

public interface Dao<T> {
	void add(T t);
	void update(T t);
	/**
	 * 根据主键查询一个对象
	 * @param id
	 * @return
	 */
	T findOne(Serializable id);
	/**
	 * 根据主键删除一个对象
	 * @param id
	 */
	void del(Serializable id);
}

二.在DaoImpl包下新建一个简单的BaseDao类(这里是重点),实现Dao接口

package com.itheima.dao.impl;

import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.itheima.dao.Dao;
import com.itheima.util.SessionFactoryUtil;

public abstract class BaseDao<T> implements Dao<T> {

	private Class clazz;//记住外面传递过来的实体类型
	public BaseDao(Class clazz){
		this.clazz = clazz;
	}
	
	public void add(T t) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			session.save(t);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}
	public T findOne(Serializable id) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			return (T)session.get(clazz, id);
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}
	public void update(T t) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			session.update(t);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}

	public void del(Serializable id) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			T bean = (T)session.get(clazz, id);
			session.delete(bean);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}
}

三.修改具体的实现类

  修改客户dao实现类

package com.itheima.dao.impl;

import java.util.List;

import com.itheima.dao.CustomerDao;
import com.itheima.domain.Customer;

public class CustomerDaoImpl extends BaseDao<Customer> implements CustomerDao {
    
	public CustomerDaoImpl(Class clazz) {
		super(Customer.class);
	}

	public List<Customer> findPageCustomer(int startIndex, int size) {
		return null;
	}
}

  修改学生dao实现类

package com.itheima.dao.impl;

import java.util.List;

import com.itheima.dao.StudentDao;
import com.itheima.domain.Student;

public class StudentDaoImpl extends BaseDao<Student> implements StudentDao {
    //继承BaseDao,没有构造方法,需要构造方法,告诉父类,查的是那个类,上面的customer一样
	public StudentDaoImpl(Class clazz) {
		super(Student.class);
	}

	public List<Student> findAll() {
		return null;
	}
}

四.service测试  

Student.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itheima.domain">
	<class name="Student" table="STUDENTS">
		<id name="id" column="ID">
			<!-- 根据数据库的能力管理主键 -->
			<generator class="native"></generator>
		</id>
		<property name="name" column="NAME"></property>
		<property name="birthday" column="BIRTHDAY"></property>
	</class>
</hibernate-mapping>

  

Cusstomer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itheima.domain">
	<class name="Customer" table="CUSTOMERS">
		<id name="id" column="ID">
			<!-- 根据数据库的能力管理主键 -->
			<generator class="native"></generator>
		</id>
		<property name="name" column="NAME"></property>
		<property name="gender" column="GENDER"></property>
	</class>
</hibernate-mapping>

把配置文件交给hibernate管理

hibernate文件hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<!-- 配置Hibernate:属性配置参考  Hibernate发型包projectetchibernate.properties -->
		<!-- JDBC的基本链接 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="connection.username">root</property>
		<property name="connection.password">sorry</property>
		<property name="connection.url">jdbc:mysql://localhost:3306/day22</property>
		<!-- 配置数据库方言 -->
		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 根据映射产生表结构的类型:
			create-drop:木有表结构创建,下次启动时删除重新创建。适合学习阶段
			create:只做创建
			update:探测表结构够的变化,对于数据库没有的,进行更新操作。适合学习阶段
			validate:对比与数据库的结构
		 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 显示sql语句及格式:开发调试阶段非常有用 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>

          <--最主要的就是这个--> <!-- 告知映射文件 --> <mapping resource="com/itheima/domain/Student.hbm.xml"/> <mapping resource="com/itheima/domain/Customer.hbm.xml"/> </session-factory> </hibernate-configuration>

 Dao测试

package com.itheima.test;

import java.util.Date;

import com.itheima.dao.CustomerDao;
import com.itheima.dao.StudentDao;
import com.itheima.dao.impl.CustomerDaoImpl;
import com.itheima.dao.impl.StudentDaoImpl;
import com.itheima.domain.Customer;
import com.itheima.domain.Student;

public class DaoTest {
	public static void main(String[] args) {
		CustomerDao cDao = new CustomerDaoImpl(Customer.class);
		StudentDao sDao = new StudentDaoImpl(Student.class);
		Customer c = new Customer();
		c.setName("刘亚雄");
		c.setGender("待定");
		cDao.add(c);
		
		Student s = new Student();
		s.setName("吕云雪");
		s.setBirthday(new Date());
		sDao.add(s);
	}
}

  结果:

customer表

student表

这就是Dao设计模型

虚线是实现接口,实线是继承类

BaseDao上有个abstract,注意:

为什么一个类里面没有抽象方法,还要定义声明为抽象类?

原因很简单:就是不让直接使用,干嘛不让?

BaseDao不让直接使用,是用来继承使用的.其实HTTPServlet就是典型,HTTPServlet是抽象类,里面有一个非抽象的方法doXXX(忘记叫什么名了)

继承后,满意的方法直接使用,不满意的方法直接覆盖掉就好了.

以上写法还不够优雅!下面来修改: 

 一.修改StudentDaoImpl实现类,其实就是去掉构造方法

package com.itheima.dao.impl;

import java.util.List;

import com.itheima.dao.StudentDao;
import com.itheima.domain.Student;

public class StudentDaoImpl extends BaseDao<Student> implements StudentDao {

//	public StudentDaoImpl(Class clazz) {
//		super(Student.class);
//	}

	public List<Student> findAll() {
		return null;
	}
}

  

 二.修改CustomerDaoImpl实现类,其实就是去掉构造方法

package com.itheima.dao.impl;

import java.util.List;

import com.itheima.dao.CustomerDao;
import com.itheima.domain.Customer;

public class CustomerDaoImpl extends BaseDao<Customer> implements CustomerDao {

//	public CustomerDaoImpl() {
//		super();
//	}

	public List<Customer> findPageCustomer(int startIndex, int size) {
		return null;
	}
}

  三.修改BaseDao类

package com.itheima.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.itheima.dao.Dao;
import com.itheima.util.SessionFactoryUtil;

public abstract class BaseDao<T> implements Dao<T> {

	private Class clazz;//实体类型
	public BaseDao(){
		//给clazz赋值:需要知道操作的是哪个实体类,从而知道操作那张表
		Type type = this.getClass().getGenericSuperclass();//得到当前实例的带有泛型类型的父类
		ParameterizedType ptype = (ParameterizedType)type;//因为父类型带有泛型信息,就可以转为ParameterizedType(参数化的泛型类型)
		clazz = (Class)ptype.getActualTypeArguments()[0];// Customer|Student.class
	}
	
	public void add(T t) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			session.save(t);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}
	public T findOne(Serializable id) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			return (T)session.get(clazz, id);
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}
	public void update(T t) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			session.update(t);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}

	

	public void del(Serializable id) {
		Session session = null;
		try{
			session = SessionFactoryUtil.getSession();
			Transaction tx = session.beginTransaction();
			T bean = (T)session.get(clazz, id);
			session.delete(bean);
			tx.commit();
		}catch(Exception e){
			throw new RuntimeException(e);
		}finally{
			session.close();
		}
	}

}

  说明:

    this代表当前对象,this有句话可以这么理解(对象永远都是这个对象,但是指向有可能向上转型)

其实上面主要就是添加以下几句代码:

Type type = this.getClass().getGenericSuperclass();//得到当前实例的带有泛型类型的父类----->CustomerDaoImpl的父类BaseDao<Customer>就是带有泛型类型的类

ParameterizedType ptype = (ParameterizedType)type;//因为父类型带有泛型信息,就可以转为ParameterizedType(参数化的泛型类型)
clazz = (Class)ptype.getActualTypeArguments()[0];// Customer|Student.class

以上几句其实就是泛型的反射应用

修改之后,优雅多了

原文地址:https://www.cnblogs.com/move22/p/5737996.html