开始学习hibernate了,跟着网上的教学视频边看边学。现在有些迷茫,不知道学这些东西,以后能不能用得上,也不知道未来会发展成什么样子,也不知道我的基础算是打好了没有,总觉得学这些框架,有点浮沙筑高台的感觉,心里很不踏实。知道的都是些表面的东西,框架底层是什么样的,看看那些源代码,想看懂很有难度啊。另外,虽说设计很有魅力,但是基石打不牢,设计也往往是空中楼阁。希望,我在学习的时候和之余,能够多多思考,多问几个为什么,深入到底层,虽说看不懂,但是看看心里总会踏实一些。
以我目前对hibernate的理解,就是它是对jdbc进行了封装,使Java对象和数据库的关系模型进行了映射,可以使程序员用对象编程的思想来操纵数据库。这样做的好处,等待以后体会吧。。。。。
hibernate框架的搭建就不说了,下载下来代码包,添加到lib目录就可以了,这里主要是举一个小例子,简单的看一下,hibernate的工作流程。
本例是建立了一个User类,将User类和数据库中的一个表进行了映射。 对要和数据库的表进行映射的Java类,是有一定的要求的:
(1)一定要有一个无参数的构造方法
(2)建议有一个id属性,这个id属性映射到表中是用来做主键的,会使效率高很多
(3)这个类最好不要是final的,因为对懒加载有影响
User类:
package com.suo.domain;
import java.util.Date;
public class User {
private int id;
private String name;
private Date birthday;
public int getId() {
return id;
}
public void setId(int 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;
}
}
其次,就是配置映射文件,这个文件很重要,它就是将User类和数据库表关联起来。
1. 首先要指定要映射的类所在的包。
2. 在class标签中,指定要映射的是哪个类,并且可以用table属性指定,要和数据库中的哪个表进行映射,默认的是和类名相同的表。
3. id标签是专门用来映射主键的,它和其他的非主键属性形式不一样,并且在id标签内部,用generator标签来指定用什么组件来生成主键。
4. property标签是用来指定其他的非主键属性
5. 在id、property标签中还有一个属性是column,可以用来指定对象中的属性和表中的哪个列进行映射,默认的是和属性名相同的列。
6. 如果对象中的某个属性不需要存储到数据库中,那么在映射文件中,就不需要配置这个属性。
User.hbm.xml:
<hibernate-mapping package="com.suo.domain">
<class name="User">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="birthday"/>
</class>
</hibernate-mapping>
然后就是对数据库的配置文件了,这里用的数据库是Mysql,对数据库进行配置有两种方式,一种是在hibernate.properties中进行配置,一种是在hibernate.cfg.xml文件中进行配置,由于后者可视性好,所以一般在xml文件中进行配置,如下:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="foo">
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 因为hibernate具有可移植性,所以此处需要指定它的方言 -->
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- 自动创建对应的表 ,create这种模式是每次重新启动程序的时候,都会把原先的表删除掉-->
<mapping resource="com/suo/domain/User.hbm.xml"/>
<!-- 指明映射文件在哪里 -->
</session-factory>
</hibernate-configuration>
接下来,就是应用了,由于读取配置文件和映射文件很耗时,所以将其抽象出来,单独组成一个类。
HibernateUtil.java:
package com.suo.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public final class HibernateUtil {
private static SessionFactory sessionFactory;
/**
* 私有的构造方法,这样就可以防止实例化这个类
*/
private HibernateUtil(){}
/**
* 因为读取配置文件和映射文件很耗时间,所以这段代码块定义成静态的,那么只加载一次就可以了
*/
static{
Configuration config=new Configuration();
config.configure();//读取配置文件,默认的是读取hibernate.cfg.xml,若文件名不是这个,也可以以参数形式指定
sessionFactory=config.buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession(){
return sessionFactory.openSession();
}
}
在Main中进行测试:
package com.suo.test;
import java.util.Date;
import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.Session;
import com.suo.domain.User;
import com.suo.hibernate.HibernateUtil;
public class Test {
public static void main(String[] args) {
User user=new User();
user.setBirthday(new Date());
user.setName("suo");
addUser(user);
System.out.println("end");
}
public static void addUser(User user){
Session session=null;
Transaction transaction=null;
try{
session=HibernateUtil.getSession();//获得一个连接
transaction=session.beginTransaction();//开启一个事务
session.save(user);
transaction.commit();/*设置为自动提交,因为hibernate默认的设置为不自动提交,
这时候使用的数据库引擎为InnoDB,支持事务*/
}catch(HibernateException e){
if(transaction!=null){
transaction.rollback();
}
e.printStackTrace();
}finally{
if(session!=null){
session.close();
}
}
}
public static User getUser(int id){
Session session=null;
try{
session=HibernateUtil.getSession();
/**
* 这里要传递两个参数,第一个是指定要到哪个表中查询(因为User.class这个实例包含了这个类的很多信息),
* 第二是这个表的主键。这两个参数即可唯一确定一个记录,一个对象。
*/
User user=(User)session.get(User.class, id);
/**
* load是懒加载,这里和get方法不同,在这里它不会立即访问数据库,而是生成一个User的子类的实例,
* 并返回,所以即使在数据库中该主键对应的记录为空,这里也会返回一个User的子类的实例,而不是空。
*/
// User user=(User)session.load(User.class, id);
// System.out.println(user.getName()+"\n"+user.getBirthday());
// System.out.println(user.getClass().getName());//可以查看user的所属的类型
return user;
}catch(HibernateException e){
e.printStackTrace();
return null;
}finally{
if(session!=null){
session.close();
}
}
}
}