Hibernate笔记(一)

初始配置:

1.建立新项目,加入相应的jar包,最好自定义一个liberary,命名为Hibernate,将需要的jar文件加入,hibernate-core,/requires,slf-nop jar

2.引入mysql的jdbc的驱动包

3.mysql中建立对应的数据库和表

4.建立hibernate配置文件(建议从原始文档copy)hibernate.cfg.xml  ,xxxxx.hbm.xml

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <!-- JDBC connection pool (use the built-in) --> <!--<property name="connection.pool_size">1</property>--> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <!-- <property name="current_session_context_class">thread</property> --> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <!--<property name="hbm2ddl.auto">update</property>--> <mapping resource="cn/edu/haut/hibernate/model/Student.hbm.xml"/> </session-factory> </hibernate-configuration>

 

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.edu.haut.hibernate.model"> <class name="Student" table="STUDENT"> <id name="id" column="id"></id> <property name="name" column="name"></property> <property name="age" column="age"></property> </class> </hibernate-mapping>

 

测试类:

import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import cn.edu.haut.hibernate.model.Student; public class StudentTest { public static void main(String[] args){ Student s=new Student(); s.setId(12); s.setName("aaa"); s.setAge(23); Configuration cfg=new Configuration(); SessionFactory sf=cfg.configure().buildSessionFactory(); Session session=sf.openSession(); session.beginTransaction(); session.save(s); session.getTransaction().commit(); session.close(); sf.close(); } }

 

建立Annotation版的hibernate:

 加入annotation的jar包:ejb3-persisitance,hibernate-commons-annotations

 

建立Teacher类和TeacherTest类测试

修改Configuration为

Configuration cfg=new AnnotationConfiguration();

 

在Teacher类上方加上   @Entity

Teacher类的方法 getId()   上加@Id  说明Id是主键

修改hibernate配置文件hibernate.cfg.xml加入

<mapping class="cn.edu.haut.hibernate.model.Teacher"/>

 

 

设置自动提示:

java-editor-editor assistance 默认的for java加入@

 

 

通过Annotation建表(若存在则自动删除):

在hibernate.cfg.xml中加入sdf

<property name="hbm2ddl.auto">create</property>

其他可选字段参考hibernate doc

 

 

实际工作中往往是先建表后建类

 

搭建日志环境 log4j 和测试环境JUnit

1.搭建日志环境:

利用slf4j的接口和log4j的实现搭建

首先删除自定义类库hibernate中的 slf4j-non-1.5.8.jar,添加log4j的jar包(log4j-1.2.16.jar),再添加slf4j中的slf4j-log4j12-1.5.8.jar包,将slf4j接口和log4j实现连接在一起,(适配器adapter模式),加入log4j的配置文件,可以copy  /hibernate-distribution-3.3.2.GA/project/etc目录下的log4j.properties文件,输出ddl语句,屏蔽掉无需语句。ok,搭建成功

 

2.搭建测试环境:

建立自己的类库MyJUnit,引入JUnit的jar包,在buildpath中加入MyJUnit

new一个source folder用来存放测试用例源文件, 建议建立和所测试类名所在包名一致的包名,建立测试类:

package cn.edu.haut.hibernate.model; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class TeacherTest { private static SessionFactory sf=null; @BeforeClass public static void beforeClass(){ sf=new AnnotationConfiguration().configure().buildSessionFactory(); } @Test public void teacherSave(){ Teacher t=new Teacher(); t.setId(114); t.setName("cccc"); t.setTitle("高级"); Configuration cfg=new AnnotationConfiguration(); SessionFactory sf=cfg.configure().buildSessionFactory(); Session session=sf.openSession(); session.beginTransaction(); session.save(t); session.getTransaction().commit(); session.close(); } @AfterClass public static void afterClass(){ sf.close(); } }

 

 

sessionfactory的建立比较耗时,写一个単例,

@BeforeClas,指的是对象初始换之前,class load之后马上执行该方法

 

JUnit的BUG:

hibernate.cfg.xml文件写错,junit有可能不报错,解决办法:
1.对sf进行try{}catch()                         2.加main方法,调用beforeClass();

 

Format Sql

  <property name="show_sql">true</property>

<property name="format_sql">true</property> 

 

 

Hibernate基础配置:

表名和类名不同:
类上方加
@Table(name="_teacher")

都加在get方法上
字段名和属性名相同
相当于默认添加
@Basic
字段名和属性名不对应:
在属性上方加
@Column(name="_name")

不需要持久化的字段:
@Transient


映射日期和时间类型:
@Temporal(TemporalType.DATE)   (只记录日期)

映射枚举类型:
@Enumerated(EnumType.STRING)

package cn.edu.haut.hibernate.model; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; @Entity @Table(name="_teacher") public class Teacher { private int id; private String name; private String title; private String yourWifeName; private Date birthday; private ZhiCheng zhicheng; @Id public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name="_name") public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getYourWifeName() { return yourWifeName; } public void setYourWifeName(String yourWifeName) { this.yourWifeName = yourWifeName; } @Temporal(TemporalType.DATE) public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Enumerated(EnumType.STRING) public ZhiCheng getZhicheng() { return zhicheng; } public void setZhicheng(ZhiCheng zhicheng) { this.zhicheng = zhicheng; } }

 

 

ID生成策略:


xml 参考doc
Annotation配置
@ID
@GenerateValue(默认是auto)

@GenerateValue(strategy=GenerationType.IDENTITY)
@GenerateValue(strategy=GenerationType.SEQUENCE)

TableGenerator(跨数据库平台,非常少用)


联合主键:
id+name
组件类实现Serializable重写equals和hashcode
xml配置:doc文档
Annotation:doc文档,主键映射

 

 

核心API

 

三种状态:


核心开发接口,三种状态


Configuration
AnnotationConfiguration.configure.buildSessionFactory();
AnnotationConfiguration.configure得到默认配置文件hibernate.cfg.xml,也可以指定别的位置

 

SessionFactory(session可以理解为数据库的连接)
Session session=sessionFactory.getCurrentFactory();

 

sessionFactory:做成単例
a.用来产生和管理Session
b.通常情况下每个应用只需一个SessionFactory
c.除非要访问多个数据库
d.关注两个方法:openSession() getCurrentSession()
   openSession()每次都是新的,需要close
   getCurrentSession从上下文找,如果有用旧的如果没有用新的
 1.用途,界定事物边界
 2.事务提交自动close
 3.current-session_context_class(jta thread)(java transaction)
      thread用connection事务

      jta使用application server提供的事务,多用于分布式


三种状态:
id自动生成的(@GeneratedValue)

Transient(new一个对象未设id)
Persistent(调用save之后)
Detached (session执行close后)

 

三种状态的区分:
a.有没有id
b.id在数据库中有没有
c.在缓中有没有id

(transaction  缓存中一个对象,无id)
(persistent 有id,内存有,数据库有,缓存有 )
(detached 内存中有,缓存中没有,数据库有)

 

 

 Session接口:
save()
delete()
load()
get()
get和load的区别:
load返回代理对象(设计模式-动态代理(设计模式中最难的)),等到真正用到时才

发出sql语句
不存在对应记录表现不一样
get直接从数据库加载不会延迟
update()
更新部分更改的字段
使用HQL语句(建议)
saveOrUpdate()
clear()

schemeExport

 

 

package cn.edu.haut.hibernate.model; import java.util.Date; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class TeacherTest { private static SessionFactory sf=null; @BeforeClass public static void beforeClass(){ sf=new AnnotationConfiguration().configure().buildSessionFactory(); } @Test public void teacherSave(){ Teacher t=new Teacher(); t.setName("cccc"); t.setTitle("高级"); t.setZhicheng(ZhiCheng.B); t.setBirthday(new Date()); Session session=sf.getCurrentSession(); session.beginTransaction(); session.save(t); System.out.println("ID="+t.getId()); session.getTransaction().commit(); } @Test public void teacherDelete(){ Teacher t=new Teacher(); t.setId(4); Session session2=sf.getCurrentSession(); session2.beginTransaction(); session2.delete(t); System.out.println("ID="+t.getId()); session2.getTransaction().commit(); } @Test public void teacherLoad(){ Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.load(Teacher.class, 5); System.out.println(t.getClass().getName());//验证是代理对象 //System.out.println("Name="+t.getName());//注意位置 session.getTransaction().commit(); } @Test public void teacherGet(){ Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.get(Teacher.class,5); System.out.println(t.getClass().getName());//验证时Teacher类 session.getTransaction().commit(); //System.out.println("Name="+t.getName());//对比Load位置 } @Test public void teacherUpdate(){ //更新detached对象,更新后变为persisitent对象 //更新transient对象会报错 //更新自己设定id的transient对象可以 Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.get(Teacher.class,5); session.getTransaction().commit(); t.setName("zhanglaoshi"); Session session2=sf.getCurrentSession(); session2.beginTransaction(); session2.update(t); session2.getTransaction().commit(); } @Test public void teacherUpdate2(){ //persistent状态的对象只要设定不同字段就会发生更新 Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.get(Teacher.class,3); t.setName("zhangsan"); session.getTransaction().commit(); } @Test public void teacherUpdate3(){ //使用HQL(EJBQL)语句 Session session=sf.getCurrentSession(); session.beginTransaction(); Query q=session.createQuery("update Teacher set name='lisi' where id='7'"); q.executeUpdate(); session.getTransaction().commit(); } @Test public void teacherSaveOrUpdate(){ //在不同时期执行save或update Teacher t=new Teacher(); t.setName("cccc"); t.setTitle("高级"); t.setZhicheng(ZhiCheng.B); t.setBirthday(new Date()); Session session=sf.getCurrentSession(); session.beginTransaction(); session.saveOrUpdate(t);//执行save session.getTransaction().commit(); t.setName("wang"); Session session2=sf.getCurrentSession(); session.beginTransaction(); session.saveOrUpdate(t);//执行update session.getTransaction().commit(); } @Test public void teacherClear(){ Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.load(Teacher.class, 5); System.out.println("Name="+t.getName()); session.clear();//清空缓存 //无论调用get()还是load(),都会先查找缓存,如果没有才会去数据库找, //调用clear()强制清除session缓存 Teacher t2=(Teacher)session.load(Teacher.class, 5); System.out.println("Name="+t2.getName()); session.getTransaction().commit(); } @Test public void teacherFlush(){ Session session=sf.getCurrentSession(); session.beginTransaction(); Teacher t=(Teacher)session.load(Teacher.class, 5); t.setName("ddddd"); session.flush();//强制内存和数据库数据同步,默认同步实在事物提交时即transaction执行commit时 t.setName("DDDDD"); session.getTransaction().commit();//执行commit时默认执行flush() } @AfterClass public static void afterClass(){ sf.close(); } }

 

关系映射:

一对一双向关联:
OneToOne
凡是双向关联设mappedBy属性

~~~ @Entity public class Wife { private int id; private String name; private Husband husband; @Id public int getId() { return id; ~~~ @OneToOne(mappedBy="wife") public Husband getHusband() { return husband; } ~~~ }

~~~ @Entity public class Husband { private Wife wife; private int id; private String name; public int getId() { return id; } @Id @GeneratedValue public String getName() { return name; } @OneToOne @JoinColumn(name="wifeID") //指定外键名字 public Wife getWife() { return wife; } ~~~ }

 

组件映射(两个对象映射到同一张表)
@Embeded

多对多的双向关联
加一张中间表

ManyToMany

 ~~~ @Entity public class Student { private int id; private String name; @Id @GeneratedValue 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; } }

~~~ @Entity public class Teacher { private int id; private String name; private Set<Student> users=new HashSet<Student>(); @Id @GeneratedValue 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; } @ManyToMany @JoinTable(name="t_s", joinColumns={@JoinColumn(name="teacher_id")}, inverseJoinColumns={@JoinColumn(name="student_id")} ) public Set<Student> getUsers() { return users; } public void setUsers(Set<Student> users) { this.users = users; } }

 

 


多对一和一对多
manyToOne
在多的一方加外键


 

 

~~~ public class Wife { private String wifeName; private int age; public String getWifeName() { return wifeName; } public void setWifeName(String name) { this.wifeName = name; } public int getAge(){ return age; } public void setAge(int age){ this.age=age; } }

~~~ @Entity public class Husband { private Wife wife; private int id; private String name; public int getId() { return id; } @Id @GeneratedValue public String getName() { return name; } @Embedded public Wife getWife() { return wife; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setWife(Wife wife) { this.wife = wife; } }

 

 

你可能感兴趣的:(Hibernate笔记(一))