• 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

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

    修改之后,优雅多了

  • 相关阅读:
    C#操作Word完全功略
    Ubuntu安装BackExec Remote Agent for Linux
    curl快速实现网速测试
    GitHub已将持续集成服务器Janky开源
    串行(Sequential)、并发(Concurrent)、并行(parallel)与分布式(distributed)
    使用ld的wrap选项替换已有库函数
    Linux获取程序编译参数
    配置Apache+Tomcat实现SSO(单点登录)
    ipad+Blackberry构建临时网络访问
    巧解 JavaScript 中的嵌套替换
  • 原文地址:https://www.cnblogs.com/move22/p/5737996.html
Copyright © 2020-2023  润新知