兑现自己的Hibernate框架之Session 方法实现
Hibernate是三大框架中相比较而言简单而且容易理解的一个框架。
Structs 2 面向于前端处理,比如说页面请求的处理,转发等。
Spring 主要是业务处理,是三者里面最难的一个框架。
Hibernate 处理持久层,专门解决数据库方面的问题,对sql语句实现封转。开发者不必自己去写jdbc语句。实现业务的很好隔离。各司其职。
Hibernate 里面有这么几个类。
1. Configuration
这个类专门用来读写配置文件的。它有一个 buildSessionFactory()方法。用来创建session工场;
2. SessionFactory 类。就是由上述的Configuration 的buildSessionFactory()方法生成;其目的是为了生成Session 类其方法是openSession();
3. Session 类。这个里面主要有三个方法。 save() delete() update();
对应数据库里面的增删改。还有一个生成事务类的方法beginTransaction(),这个类也 是最关键的类;
4 . Transaction 事务。主要用来提交事务。其方法 Commit();
在看下面代码之前有必要先对hibernate有个大概的了解。熟悉下其配置文件。
在工程的src目录下有个hibernate.cfg.xml的配置文件。这个名字一般是默认的。然后它里面的内容是连接数据库的jdbc语句。
<hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.url">jdbc:mysql://localhost:3306/dir</property> <property name="connection.username">root</property> <property name="connection.password">sa</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="myeclipse.connection.profile">mysql</property> <mapping resource="bean/Student.hbm.xml" /> </session-factory> </hibernate-configuration>
然后,每个类都对应数据库里面的一张表,因此,产生了一系列的配置文件。配置文件的名字也很有规律。 类名.hbm.xml 然后在hibernate.cfg.xml里面引入。
这个类名.hbm.xml配置文件大概是如下这个样子;
<hibernate-mapping> <class name="com.wsx.hibernate.Student" table="student"> <id name="id" column="id" /> <property name="name" column="name" /> <property name="age" column="age" /> </class> </hibernate-mapping>
前面的name里面的是该类的属性。后面试该属性对应的table表里面的某个属性;
大概读取流程就是先从配置文件里面读取连接数据库的相关信息。连接成功了之后将每个类和某个数据库下面某个表相关联。然后将类的属性和表的属性一一对应。然后我们只需要操作类即可。这样通过配置文件就可以找到该类对应应该操作的表。将数据库这个面向关系的东西通过面向对象来替代了。
例子:
比如我要将一个student类添加到student表里这个表有id,name,age三个属性;
Student stu = new Student(); stu.setAge(19); stu.setName("fdg"); stu.setId(1); Configuration con = new Configuration(); SessionFactory sf = con.configure("/hibernate.cfg.xml") .buildSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Serializable se=session.save(stu); System.out.println(se); session.getTransaction().commit(); session.close();
翻查源码。发现save方法是这样的:
public Serializable save(Object object) throws HibernateException;
再一看原来session是个接口
public interface Session extends Serializable
这里面的serializable可是一个非常重要的东西。它的意思是序列化。
这里有文章详细解读:http://www.2cto.com/kf/201109/103111.html
在这种找不到save底层如何与数据库相连接,以及sql语句也寻不到的情况下。我们有必要自己去想明白,它是如何实现的。
这里,我自己定义一个Session类。这个类我们定义一个save方法;
假定,我们已经从配置文件里面获得了表和类之间的关系。然后我们保存在map映射关系中。
我们就拿save方法作为例子;
package com.wsx.hibernate; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Session { private String tableName="student"; private Map<String,String> map=new HashMap<String,String>(); private String[] methods=null; //创建语句类型; private static int save=0; private static int update=1; private static int delete=2; public Session (){ //key 值是表名 ,value是类属性 map.put("id", "id"); map.put("name", "name"); map.put("age", "age"); methods=new String[map.size()]; } public Connection getConn(){ Connection conn=null; try { Class.forName("com.mysql.jdbc.Driver"); conn=conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/dir","root","sa"); } catch (Exception e) { System.out.println("异常:"+e.getLocalizedMessage()); } return conn; } /** * 用来向数据库里面添加内容的 * @param s student对象; * @throws Exception */ public void save(Student s) throws Exception{ String sql=create(Session.save); Connection conn=getConn(); java.sql.PreparedStatement ps= conn.prepareStatement(sql); int len=methods.length; for(int i=0;i<len;i++){ //根据方法名获取对应的方法; Method mo= s.getClass().getMethod(methods[i]); //获取方法的返回类型 Class c=mo.getReturnType(); //判断返回类型 if(c.getName().equals("java.lang.String")){ //根据不同的返回类型获取返回值。如果是void类型的话,那么返回类型为void。返回值为null String value=(String)mo.invoke(s); ps.setString(i+1,value); } if(c.getName().equals("int")){ Integer value=(Integer)mo.invoke(s); ps.setInt(i+1,value); } } ps.executeUpdate(); ps.close(); conn.close(); System.out.println("添加成功"); } private String create(int type) { //有几个属性。 String str1=""; //有几个待插入的位置 String str2=""; Set<String> set=map.keySet(); int index=0; for(String s:set){ str1+=s+","; str2+="? ,"; //get方法方法名是属性名的首字母大写然后加上get String value=map.get(s); value=Character.toUpperCase(value.charAt(0))+value.substring(1,value.length()); value="get"+value; //将方法名放入到方法数组里面 methods[index++]=value; } //拼成的字符串最后面多了一个逗号。所以截取除了最后一个字符之外的其他字符 str1=str1.substring(0,str1.length()-1); str2=str2.substring(0,str2.length()-1); System.out.println(str1+" "+str2); String sql=null; if(type==0){ //save sql="insert into "+tableName +" ("+str1+") values ("+str2+")"; }else if(type==1){ //update // sql="update "+tableName+" set name=? ,age=? where id=?"; }else if(type==2){//delete //sql="delete from "+tableName+" where id =?"; } return sql; } }
这里用到了用到了动态反射的相关东西。通过方法名,来判断该方法的返回类型和返回值。
下面是测试类;
package com.wsx.hibernate; public class HibernateSave { public static void main(String[] args) { Student stu=new Student(); stu.setId(4); stu.setName("wsx"); stu.setAge(21); Session session=new Session(); try { session.save(stu); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
然后将会在数据库对应的表里面看到插入的数据。这里就是save方法的实现。!