hibernate1.2
来源:互联网 发布:淘宝怎么使用不了花呗 编辑:程序博客网 时间:2024/05/21 08:58
Junit (junit-4.8.jar )
Junit(bug) 测试部提示错误具体信息的时候2种常用的方法
1、用try {} catch(){}
2、main()方法
例子程序如下
- package com.demo.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 beforClass() {
- // try {
- sf = new AnnotationConfiguration().configure().buildSessionFactory();
- // } catch (Exception e) {
- // e.printStackTrace();
- // }
- }
- @Test
- public void testTeacherSave() {
- Teacher t = new Teacher();
- t.setId(1);
- t.setName("t1");
- t.setTitle("中级");
- Session session = sf.openSession();
- session.beginTransaction();
- session.save(t);
- session.getTransaction().commit();
- session.close();
- }
- // public static void main() {
- // beforClass();
- // }
- @AfterClass
- public static void afterClass() {
- sf.close();
- }
- }
- <property name="format_sql">true</property>
- 更加规范和漂亮的建表语句
- 10:49:19,563 INFO SchemaExport:226 - Running hbm2ddl schema export
- 10:49:19,575 DEBUG SchemaExport:242 - import file not found: /import.sql
- 10:49:19,575 INFO SchemaExport:251 - exporting generated schema to database
- 10:49:19,577 DEBUG SchemaExport:377 -
- drop table if exists Student
- 10:49:19,935 DEBUG SchemaExport:377 -
- drop table if exists Teacher
- 10:49:19,968 DEBUG SchemaExport:377 -
- create table Student (
- id integer not null,
- name varchar(255),
- age integer,
- primary key (id)
- )
- 10:49:20,012 DEBUG SchemaExport:377 -
- create table Teacher (
- id integer not null,
- name varchar(255),
- title varchar(255),
- primary key (id)
- )
- 10:49:20,031 INFO SchemaExport:268 - schema export complete
- Hibernate:
- insert
- into
- Teacher
- (name, title, id)
- values
- (?, ?, ?)
1、 表名和类名不同,对表名进行配置
a) Annotation:@Table
b) Xml:自己查询
2、 字段名和属性相同
a) 默认为@Basic
b) Xml中不用写column
映射文件表名指定
<class name="Student" table="_student">
Annotation表名指定
@Table(name="_Teacher") (import javax.persistence.Table;)
public class Teacher{ }
1、 字段名和属性名不同
a) Annotation:@Column
@Column(name="_title")
public String getTitle() {
return title;
}
1、 不需要psersistence的字段
a) Annotation:@Transient
b) Xml:不写
//@Transient 隐藏数据库里面的字段public String getYouWifeName() {
return youWifeName;
}
1、 映射日期与时间类型,指定时间精度
a) Annotation:@Temporal
b) Xml:指定type
一般在注解(@)里面有value 可以不写,直接写后面的值
java类里面的日期一般用 import java.util.Date;
xml里面 <property name="name" type="date"/>
@Annotation
@Temporal(TemporalType.DATE) //只记录日期
public Date getDate() {
return date;
}
1、 映射枚举类型
a) Annotation:@Enumerated
b) Xml:麻烦
@Enumerated(EnumType.STRING)public ZhiCheng getZhiCheng() {
return zhiCheng;
}
public enum ZhiCheng {
A, B, C
}
第13课 ID主键生成策略
一、 Xml方式
<id>标签必须配置在<class>标签内第一个位置。由一个字段构成主键,如果是复杂主键<composite-id>标签
被映射的类必须定义对应数据库表主键字段。大多数类有一个JavaBeans风格的属性, 为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。
<id
name="propertyName" (1)
type="typename" (2)
column="column_name" (3)
unsaved-value="null|any|none|undefined|id_value" (4)
access="field|property|ClassName" (5)
node="element-name|@attribute-name|element/@attribute|.">
<generatorclass="generatorClass"/>
</id>
(1) name (可选): 标识属性的名字(实体类的属性)。
(2) type (可选): 标识Hibernate类型的名字(省略则使用hibernate默认类型),也可以自己配置其它hbernate类型(integer, long, short, float,double, character, byte, boolean, yes_no, true_false)
(2) length(可选):当type为varchar时,设置字段长度
(3) column (可选 - 默认为属性名): 主键字段的名字(省略则取name为字段名)。
(4) unsaved-value (可选 - 默认为一个切合实际(sensible)的值): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。 这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注) 但未再次持久化的实例区分开来。
(5) access (可选 - 默认为property): Hibernate用来访问属性值的策略。
如果 name属性不存在,会认为这个类没有标识属性。
unsaved-value 属性在Hibernate3中几乎不再需要。
还有一个另外的<composite-id>定义可以访问旧式的多主键数据。 我们强烈不建议使用这种方式。
<generator>元素(主键生成策略)
主键生成策略是必须配置
用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数, 用<param>元素来传递。
<id name="id"type="long" column="cat_id">
<generator class="org.hibernate.id.TableHiLoGenerator">
<param name="table">uid_table</param>
<param name="column">next_hi_value_column</param>
</generator>
</id>
所有的生成器都实现org.hibernate.id.IdentifierGenerator接口。 这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然, Hibernate提供了很多内置的实现。下面是一些内置生成器的快捷名字:
increment
用于为long, short或者int类型生成 唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。
identity
对DB2,MySQL, MS SQL Server,Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。 (数据库自增)
sequence
在DB2,PostgreSQL, Oracle, SAPDB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。(数据库自增)
hilo
使用一个高/低位算法高效的生成long, short 或者 int类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key和next_hi)作为高位值的来源。 高/低位算法生成的标识符只在一个特定的数据库中是唯一的。
seqhilo
使用一个高/低位算法来高效的生成long, short 或者 int类型的标识符,给定一个数据库序列(sequence)的名字。
uuid
用一个128-bit的UUID算法生成字符串类型的标识符, 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串,它的生成是由hibernate生成,一般不会重复。
UUID包含:IP地址,JVM的启动时间(精确到1/4秒),系统时间和一个计数器值(在JVM中唯一)。 在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了
guid
在MS SQL Server 和 MySQL 中使用数据库生成的GUID字符串。
native
根据底层数据库的能力选择identity,sequence 或者hilo中的一个。(数据库自增)
assigned
让应用程序在save()之前为对象分配一个标示符。这是 <generator>元素没有指定时的默认生成策略。(如果是手动分配,则需要设置此配置)
select
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
foreign
使用另外一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。
二、 annotateon方式
使用@GeneratedValue(strategy=GenerationType)注解可以定义该标识符的生成策略
Strategy有四个值:
① 、AUTO- 可以是identity column类型,或者sequence类型或者table类型,取决于不同的底层数据库.
相当于native
② 、TABLE- 使用表保存id值
③ 、IDENTITY- identity column
④ 、SEQUENCE- sequence
注意:auto是默认值,也就是说没有后的参数则表示为auto
- 1、getCurrentSession()与openSession()的区别?
- * 采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()
- 创建的session则不会
- * 采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()
- 创建的session必须手动关闭
- 2、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
- * 如果使用的是本地事务(jdbc事务)
- <property name="hibernate.current_session_context_class">thread</property>
- * 如果使用的是全局事务(jta事务)
- <property name="hibernate.current_session_context_class">jta</property>
- //uuid
- <class name="com.demo.hibernate.Student">
- <id name="id">
- <generator class="uuid"></generator>
- </id>
- <property name="name"/>
- <property name="age"/>
- </class>
- private String id; //uuid 的id必须是String类型
- //native
- <class name="com.demo.hibernate.Student">
- <id name="id">
- <generator class="native"></generator>
- </id>
- <property name="name"/>
- <property name="age"/>
- </class>
- private int id; /native 的id是int类型 相当于auto_increment
- package com.demo.hibernate.model;
- import java.util.Date;
- import javax.persistence.Entity;
- import javax.persistence.EnumType;
- import javax.persistence.Enumerated;
- import javax.persistence.Id;
- import javax.persistence.Temporal;
- import javax.persistence.TemporalType;
- @Entity //实体类
- // @Table(name="_teacher")
- public class Teacher {
- private int id;
- private String name;
- private String title;
- private String youWifeName;
- private Date date;
- private ZhiCheng zhiCheng;
- @Enumerated(EnumType.STRING)
- public ZhiCheng getZhiCheng() {
- return zhiCheng;
- }
- public void setZhiCheng(ZhiCheng zhiCheng) {
- this.zhiCheng = zhiCheng;
- }
- //@Temporal(TemporalType.DATE) //只记录日期
- public Date getDate() {
- return date;
- }
- public void setDate(Date date) {
- this.date = date;
- }
- //@Transient 隐藏数据库里面的字段
- public String getYouWifeName() {
- return youWifeName;
- }
- public void setYouWifeName(String youWifeName) {
- this.youWifeName = youWifeName;
- }
- @Id //主键
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- //@Column(name="_title")
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
如果id生成策略使用native 在mysql使用auto_increment , 在oracle 使用sequence
,SQL Server 使用 identity
@GeneratedValue
public int getId() {
return id;
}
相当于xml里面的native
.. 映射主键属性
使用@Id注解可以将实体bean中的某个属性定义为标识符(identifier). 该属性的值可以通过应用自身进行设置, 也可以通过Hiberante生成(推荐).
使用 @GeneratedValue注解可以定义该标识符的生成策略:
- AUTO - 可以是identity column类型,或者sequence类型或者table类型,取决于不同的底层数据库.
- TABLE - 使用表保存id值
- IDENTITY - identity column
- SEQUENCE - sequence
@GeneratedValue(strategy=GenerationType.IDENTITY) mysql
- @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")
- public class Teacher { }
- name="teacherSEQ" 这个name的指的是生成器的名字
- sequenceName="teacherSEQ_DB" 表示数据库里面的名字
- @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")
- public int getId() {
- return id;
- }
- // 经典留在这里 hibernate.cfg.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>
- <!--
- <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">bjsxt</property>
- <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
- -->
- <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
- <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
- <property name="connection.username">scott</property>
- <property name="connection.password">tiger</property>
- <property name="dialect">org.hibernate.dialect.OracleDialect</property>
- <!-- JDBC connection pool (use the built-in) -->
- <property name="connection.pool_size">1</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>
- <property name="format_sql">true</property>
- <!-- Drop and re-create the database schema on startup -->
- <property name="hbm2ddl.auto">update</property>
- <mapping resource="com/demo/hibernate/Student.hbm.xml"/>
- <mapping class="com.demo.hibernate.Teacher"/>
- </session-factory>
- </hibernate-configuration>
- package com.demo.hibernate;
- public class Student {
- private int id;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- private String name;
- private int age;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
- package com.demo.hibernate;
- import java.util.Date;
- import javax.persistence.Entity;
- import javax.persistence.EnumType;
- import javax.persistence.Enumerated;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.SequenceGenerator;
- import javax.persistence.Temporal;
- import javax.persistence.TemporalType;
- import org.hibernate.annotations.GenericGenerator;
- @Entity //实体类
- @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")
- public class Teacher {
- private int id;
- private String name;
- private String title;
- @Id
- @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- <?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="com.demo.hibernate">
- <class name="Student">
- <id name="id">
- <generator class="native"></generator>
- </id>
- <property name="name"/>
- <property name="age"/>
- </class>
- </hibernate-mapping>
- package com.demo.hibernate;
- import java.util.Date;
- 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;
- import com.demo.hibernate.Teacher;
- import com.demo.hibernate.ZhiCheng;
- public class HibernateIDTest {
- private static SessionFactory sf = null;
- @BeforeClass
- public static void beforClass() {
- try {
- sf = new AnnotationConfiguration().configure().buildSessionFactory();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Test
- public void testStudentSave() {
- Student s = new Student();
- s.setName("zhangsan");
- s.setAge(8);
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.save(s);
- session.getTransaction().commit();
- }
- @Test
- public void testTeacherSave() {
- Teacher t = new Teacher();
- t.setName("t1");
- t.setTitle("ffff");
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.save(t);
- session.getTransaction().commit();
- }
- @AfterClass
- public static void afterClass() {
- sf.close();
- }
- public static void main(String[] args) {
- beforClass();
- }
- }
表生成器,可以使数据库和数据跨平台
- @javax.persistence.TableGenerator(
- name="EMP_GEN",
- table="GENERATOR_TABLE",
- pkColumnName = "key",
- valueColumnName = "hi"
- pkColumnValue="EMP",
- allocationSize=20
- )
联合主键
1、实现序列号
2、重写equals和hashCode
- package com.demo.hibernate;
- public class StudentPK implements java.io.Serializable {
- private int id;
- private String name;
- 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;
- }
- @Override
- public boolean equals(Object o) {
- if(o instanceof StudentPK) {
- StudentPK pk = (StudentPK)o;
- if(this.id == pk.getId() && this.name.equals(pk.getName())) {
- return true;
- }
- }
- return false;
- }
- @Override
- public int hashCode() { // 就是在相同哈希码中找对象进行equals 相同的就拿出来
- return this.name.hashCode();
- }
- }
2、annotation方式
下面是定义组合主键的几种语法:
将组件类注解为@Embeddable,并将组件的属性注解为@Id
将组件的属性注解为@EmbeddedId
将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id
a) 将组件类注解为@Embeddable,并将组件的属性注解为@Id
组件类:
@Embeddable
public class TeacherPK implementsjava.io.Serializable{
private int id;
private String name;
public int getId() {return id; }
public void setId(int id) {this.id = id;}
public String getName() { return name;}
public void setName(Stringname) { this.name = name;}
@Override
public boolean equals(Object o) { ……}
@Override
public int hashCode() { return this.name.hashCode(); }
}
将组件类的属性注解为@Id,实体类中组件的引用
@Entity
public class Teacher {
private TeacherPK pk;
private String title;
@Id
public TeacherPK getPk(){
return pk;
}}
b) 将组件的属性注解为@EmbeddedId
注意:只需要在实体类中表示复合主键属性前注解为@Entity,表示此主键是一个复合主键
注意了,复合主键类不需要任何的注意。
@Entity
public class Teacher {
private TeacherPK pk;
private String title;
@EmbeddedId
public TeacherPK getPk(){
return pk;
}}
c) 类注解为@IdClass,主键的属性都注解为@Id
需要将复合主键类建立好,不需要进行任何注解
在实体类中不需要进行复合主键类的引用
需要在实体类前面注解为@IdClass,并且指定一个value属性,值为复合主键类的class
需要在实体类中进行复合主键成员属性前面注解为@Id
如下:
@Entity
@IdClass(TeacherPK.class)
public class Teacher {
//private TeacherPK pk;//不再需要
private int id;
private String name;
@Id
public int getId() {return id; }
public void setId(int id) { this.id = id; }
@Id
public String getName() {return name;}
public void setName(Stringname) {this.name = name;
}}
- package com.demo.hibernate;
- import javax.persistence.Embeddable;
- // @Embeddable //可以被嵌入的,就是说这个类的对象是另一个类的一部分 @Id
- public class TeacherPK implements java.io.Serializable {
- private int id;
- private String name;
- 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;
- }
- @Override
- public boolean equals(Object o) {
- if(o instanceof TeacherPK) {
- TeacherPK pk = (TeacherPK)o;
- if(this.id == pk.getId() && this.name.equals(pk.getName())) {
- return true;
- }
- }
- return false;
- }
- @Override
- public int hashCode() { // 就是在相同哈希码中找对象进行equals 相同的就拿出来
- return this.name.hashCode();
- }
- }
- package com.demo.hibernate;
- import java.util.Date;
- import javax.persistence.EmbeddedId;
- import javax.persistence.Entity;
- import javax.persistence.EnumType;
- import javax.persistence.Enumerated;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.IdClass;
- import javax.persistence.SequenceGenerator;
- import javax.persistence.Temporal;
- import javax.persistence.TemporalType;
- import org.hibernate.annotations.GenericGenerator;
- @Entity //实体类
- @IdClass(TeacherPK.class)
- public class Teacher {
- private TeacherPK pk;
- private int id;
- private String name;
- @Id
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- @Id
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- // @Id
- /*@EmbeddedId
- public TeacherPK getPk() {
- return pk;
- }
- public void setPk(TeacherPK pk) {
- this.pk = pk;
- }*/
- private String title;
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- }
第14课 Hibernate核心开发接口(重点)
一、 Configuration(AnnotationConfiguration)
作用:进行配置信息的管理
目标:用来产生SessionFactory
可以在configure方法中指定hibernate配置文件,默认(不指定)时在classpath下加载hibernate.cfg.xml文件
加载默认的hibernate的配置文件
sessionFactory = newAnnotationConfiguration().configure().buildSessionFactory();
加载指定hibernate的配置文件
sessionFactory=newnnotationConfiguration().configure("hibernate.xml").buildSessionFactory();
只需要关注一个方法:buildSessionFactory();
二、 SessionFactory
作用:主要用于产生Session的工厂(数据库连接池)
当它产生一个Session时,会从数据库连接池取出一个连接,交给这个Session
Session session = sessionFactory.getCurrentSession();
并且可以通过这个Session取出这个连接
关注两个方法:
getCurrentSession():表示当前环境没有Session时,则创建一个,否则不用创建
openSession(): 表示创建一个Session(3.0以后不常用),使用后需要关闭这个Session
两方法的区别:
①、openSession永远是每次都打开一个新的Session,而getCurrentSession不是,是从上下文找、只有当前没有Session时,才创建一个新的Session
②、OpenSession需要手动close,getCurrentSession不需要手动close,事务提交自动close
③、getCurrentSession界定事务边界
上下文:
所指的上下文是指hibernate配置文件(hibernate.cfg.xml)中的“current_session_context_class”所指的值:(可取值:jta|thread|managed|custom.Class)
<property name="current_session_context_class">thread</property>
常用的是:①、thread:是从上下文找、只有当前没有Session时,才创建一个新的Session,主要从数据界定事务
②、jta:主要从分布式界定事务,运行时需要Application Server来支持(Tomcat不支持)
③、managed:不常用
④、custom.Class:不常用
三、 Session
1、 管理一个数据库的任务单元
2、 save();
session.save(Object)
session的save方法是向数据库中保存一个对象,这个方法产生对象的三种状态
3、 delete()
session.delete(Object)
Object对象需要有ID
对象删除后,对象状态为Transistent状态
4、 load()
格式: Session.load(Class arg0,Serializable arg1) throws HibernateException
*arg0:需要加载对象的类,例如:User.class
*arg1:查询条件(实现了序列化接口的对象):例"4028818a245fdd0301245fdd06380001"字符串已经实现了序列化接口。如果是数值类类型,则hibernate会自动使用包装类,例如 1
* 此方法返回类型为Object,但返回的是代理对象。
* 执行此方法时不会立即发出查询SQL语句。只有在使用对象时,它才发出查询SQL语句,加载对象。
* 因为load方法实现了lazy(称为延迟加载、赖加载)
* 延迟加载:只有真正使用这个对象的时候,才加载(才发出SQL语句)
*hibernate延迟加载实现原理是代理方式。
* 采用load()方法加载数据,如果数据库中没有相应的记录,则会抛出异常对象不找到(org.hibernate.ObjectNotFoundException)
try {
session =sf.openSession();
session.beginTransaction();
User user =(User)session.load(User.class,1);
//只有在使用对象时,它才发出查询SQL语句,加载对象。
System.out.println("user.name=" + user.getName());
//因为此的user为persistent状态,所以数据库进行同步为龙哥。
user.setName("发哥");
session.getTransaction().commit();
} catch (HibernateExceptione) {
e.printStackTrace();
session.getTransaction().rollback();
} finally{
if (session != null){
if(session.isOpen()){
session.close();
}
}
}
5、 Get()
格式:Session.get(Class arg0,Serializable arg1)方法
* arg0:需要加载对象的类,例如:User.class
* arg1:查询条件(实现了序列化接口的对象):
例"4028818a245fdd0301245fdd06380001"字符串已经实现了序列化接口。如果是基数类型,则hibernate会自动转换成包装类,如 1
返回值: 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载的对象就可以了。
如果数据不存在,则返回null;
注:执行此方法时立即发出查询SQL语句。加载User对象
加载数据库中存在的数据,代码如下:
try {
session =sf.openSession();
session.beginTransaction();
* 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载的对象就可以了。
如果数据不存在,则返回null
* 执行此方法时立即发出查询SQL语句。加载User对象。
*/
User user = (User)session.get(User.class, 1);
//数据加载完后的状态为persistent状态。数据将与数据库同步。
System.out.println("user.name=" + user.getName());
//因为此的user为persistent状态,所以数据库进行同步为龙哥。
user.setName("龙哥");
session.getTransaction().commit();
} catch(HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally{
if (session != null){
if(session.isOpen()){
session.close();
}
}
6、 load()与get()区别
①、 不存在对应记录时表现不一样;
②、 load返回的是代理对象,等到真正使用对象的内容时才发出sql语句,这样就要求在第一次使用对象时,要求session处于open状态,否则出错
③、 get直接从数据库加载,不会延迟加载
get()和load()只根据主键查询,不能根据其它字段查询,如果想根据非主键查询,可以使用HQL
7、 update()
① 、用来更新detached对象,更新完成后转为为persistent状态(默认更新全部字段)
② 更新transient对象会报错(没有ID)
③ 更新自己设定ID的transient对象可以(默认更新全部字段)
④ persistent状态的对象,只要设定字段不同的值,在session提交时,会自动更新(默认更新全部字段)
⑤ 更新部分更新的字段(更改了哪个字段就更新哪个字段的内容)
a) 方法1:update/updatable属性
xml:设定<property>标签的update属性,设置在更新时是否参数更新
<property name="name" update="false"/>
注意:update可取值为true(默认):参与更新;false:更新时不参与更新
annotateon:设定@Column的updatable属性值,true参与更新,false:不参与更新
@Column(updatable=false)
public String getTitle(){return title;}
注意:此种方法很少用,因为它不灵活
b) 方法二:dynamic-update属性
注意:此方法目前只适合xml方式,JAP1.0annotation没有对应的
在实体类的映射文件中的<class>标签中,使用dynamic-update属性,true:表示修改了哪个字段就更新哪个字段,其它字段不更新,但要求是同一个session(不能跨session),如果跨了session同样会更新所有的字段内容。
<class name="com.bjsxt.Student" dynamic-update="true">
代码:
@Test
public void testUpdate5() {
Sessionsession = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s =(Student)session.get(Student.class, 1);
s.setName("zhangsan5");
//提交时,会只更新name字段,因为此时的s为persistent状态
session.getTransaction().commit();
s.setName("z4");
Sessionsession2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
//更新时,会更新所有的字段,因为此时的s不是persistent状态
session2.update(s);
session2.getTransaction().commit(); }
如果需要跨session实现更新修改的部分字段,需要使用session.merget()方法,合并字段内容
@Test
public void testUpdate6() {
Sessionsession = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s =(Student)session.get(Student.class, 1);
s.setName("zhangsan6");
session.getTransaction().commit();
s.setName("z4");
Sessionsession2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
session2.merge(s);
session2.getTransaction().commit()}
这样虽然可以实现部分字段更新,但这样会多出一条select语句,因为在字段数据合并时,需要比较字段内容是否已变化,就需要从数据库中取出这条记录进行比较
c) 使用HQL(EJBQL)面向对象的查询语言(建议)
@Test
public void testUpdate7() {
Sessionsession = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q =session.createQuery(
"update Student s sets.name='z5' where s.id = 1");
q.executeUpdate();
session.getTransaction().commit();
}
8、 saveOrUpdate()
在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save
9、 clear()
清除session缓存
无论是load还是get,都会首先查找缓存(一级缓存,也叫session级缓存),如果没有,才会去数据库查找,调用clear()方法可以强制清除session缓存
Session session= sessionFactory.getCurrentSession();
session.beginTransaction();
Teacher t =(Teacher)session.load(Teacher.class, 1);
System.out.println(t.getName());
session.clear();
Teacher t2 =(Teacher)session.load(Teacher.class, 1);
System.out.println(t2.getName());
session.getTransaction().commit();
注意:这样就会发出两条SELECT语句,如果把session.clear()去除,则只会发出一条SELECT语句,因为第二次load时,是使用session缓存中ID为1的对象,而这个对象已经在第一次load到缓存中 了。
10、 flush()
在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令。
Session.flush功能:
n 清理缓存;
n 执行sql(确定是执行SQL语句(确定生成update、insert、delete语句等),然后执行SQL语句。)
Session在什么情况下执行flush:
① 默认在事务提交时执行;
注意:flush时,可以自己设定,使用session.setFlushMode(FlushMode)来指定。
session.setFlushMode(FlushMode);
FlushMode的枚举值:
l FlushMode.ALWAYS:任务一条SQL语句,都会flush一次
l FlushMode.AUTO :自动flush(默认)
l FlushMode.COMMIT: 只有在commit时才flush
l FlushMode.MANUAL:手动flush。
l FlushMode.NEVER :永远不flush 此选项在性能优化时可能用,比如session取数据为只读时用,这样就
不需要与数据库同步了
注意:设置flush模式时,需要在session开启事务之前设置。
② 可以显示的调用flush;
③ 在执行查询前,如:iterate.
注:如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。
11、 evict()
例如:session.evict(user)
作用:从session缓存(EntityEntries属性)中逐出该对象
但是与commit同时使用,会抛出异常
session = HibernateUtils.getSession();
tx = session.beginTransaction();
User1 user = new User1();
user.setName("李四");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//利用Hibernate将实体类对象保存到数据库中,因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理,不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
session.save(user);
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。
tx.commit();
解决在逐出session缓存中的对象不抛出异常的方法:
在session.evict()之前进行显示的调用session.flush()方法就可以了。
session.save(user);
//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false
session.flush();
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。
tx.commit();
hibernate.current_session_context_class
jta
|thread (<property name="current_session_context_class">thread</property>)
jta 是针对于分布式,即多个数据库
thread 是针对于一个数据库
第15课 持久化对象的三种状态
一、 瞬时对象(Transient Object):
使用new操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收
二、 持久化对象(Persistent Object):
持久实例是任何具有数据库标识的实例,它有持久化管理器Session统一管理,持久实例是在事务中进行操作的----它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。
三、 离线对象(Detached Object):
Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受hibernate管理。
四、 三种状态的区分:
1、 有没有ID,(如果没有则是Transient状态)
2、 ID在数据库中有没有
3、 在内存里有没有(session缓存)
五、 总结:
Transient对象:随时可能被垃圾回收器回收(在数据库中没有于之对应的记录,应为是new初始化),而执行save()方法后,就变为Persistent对象(持久性对象),没有纳入session的管理
内存中一个对象,没有ID,缓存中也没有
Persistent对象:在数据库有存在的对应的记录,纳入session管理。在清理缓存(脏数据检查)的时候,会和数据库同步。
内存中有、缓存中有、数据库有(ID)
Detached对象:也可能被垃圾回收器回收掉(数据库中存在对应的记录,只是没有任何对象引用它是指session引用),注引状态经过Persistent状态,没有纳入session的管理
内存有、缓存没有、数据库有(ID)
————————————————————————————
@Column(updatable=false) // 不要让此字段更新
public String getYouWifeName() {
return youWifeName;
}
- <class name="com.demo.hibernate.Student" dynamic-update="true"> 动态更新,在数据库里面只更新你要设置的,其他的不执行,提高效率。 Annotation 没有,因此使用的时候用xml
- @Test
- public void testUpload5() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- s.setName("tianshan");
- session.getTransaction().commit();
- }
session常用的方法
- package com.demo.hibernate;
- 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;
- import com.demo.hibernate.Teacher;
- import com.demo.hibernate.Student;
- public class HibernateCoreAPITest {
- private static SessionFactory sf = null;
- @BeforeClass
- public static void beforClass() {
- try {
- sf = new AnnotationConfiguration().configure().buildSessionFactory();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Test
- public void testStudentSave() {
- Student s = new Student();
- s.setId(2);
- s.setName("ff");
- s.setAge(8);
- // Session session1 = sf.openSession(); //用于是创建新的session
- Session session = sf.getCurrentSession(); //如果原来的session 没有关闭 用原来的
- session.beginTransaction();
- session.save(s);
- session.getTransaction().commit();
- }
- /* 以下是Session里面常用方法
- * 1、session 里面有一个缓存
- * 2、拿出来的对象有三个状态
- * 3、缓存与数据库之间同步
- */
- @Test
- public void testSaveWith3State() {
- Teacher t = new Teacher();
- t.setName("ggg");
- t.setTitle("hhh");
- t.setYouWifeName("uuu");
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.save(t);
- System.out.println(t.getId());
- session.getTransaction().commit();
- System.out.println(t.getId());
- }
- @Test
- public void testDelete() {
- Teacher t = new Teacher();
- t.setName("mmm");
- t.setTitle("ffff");
- t.setYouWifeName("hhh");
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.save(t);
- System.out.println(t.getId());
- session.getTransaction().commit();
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- session2.delete(t);
- session2.getTransaction().commit();
- }
- @Test
- public void testDelete2() {
- Teacher t = new Teacher();
- t.setId(2);
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.delete(t);
- session.beginTransaction().commit();
- }
- @Test
- public void testLoad() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Teacher t = (Teacher)session.load(Teacher.class, 1);
- session.beginTransaction().commit();
- System.out.println(t.getClass()); //证明是否是代理对象
- // System.out.println(t.getName());
- }
- @Test
- public void testGet() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Teacher t = (Teacher)session.get(Teacher.class, 1);
- session.beginTransaction().commit();
- System.out.println(t.getClass()); //证明是否是代理对象
- // System.out.println(t.getName());
- }
- @Test
- public void testUpdate1() {
- // Detached ----> Persistent
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Teacher t = (Teacher)session.get(Teacher.class, 1);
- session.beginTransaction().commit();
- t.setName("zhongguo");
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- session2.update(t);
- session2.beginTransaction().commit();
- //Persistent
- }
- @Test
- public void testUpdate2() {
- // Transient ---> Persistent 不行 因为没有ID
- Teacher t = new Teacher();
- t.setName("zhongguo");
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- session2.update(t);
- session2.beginTransaction().commit();
- //Persistent
- }
- @Test
- public void testUpdate3() {
- // Transient ---> Persistent 不行 因为没有ID
- Teacher t = new Teacher();
- t.setId(1); //手动设置ID 可以 前提是数据库里面有对应的记录
- t.setName("zhongguo");
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- session2.update(t);
- session2.beginTransaction().commit();
- //Persistent
- }
- @Test
- public void testUpdate4() {
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- Teacher t = (Teacher)session2.get(Teacher.class, 1);
- t.setName("mein");
- session2.beginTransaction().commit();
- }
- @Test
- public void testUpload5() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- s.setName("tianshan");
- session.getTransaction().commit();
- }
- @Test
- public void testUpload6() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- s.setName("wangsan");
- session.getTransaction().commit();
- s.setName("huangshan");
- //上面是Detached,下面新开启Session,因此跟上面没比较,所以全部更新
- Session session1 = sf.getCurrentSession();
- session1.beginTransaction();
- session1.update(s);
- session1.getTransaction().commit();
- }
- @Test
- public void testUpload7() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- s.setName("wangsan");
- session.getTransaction().commit();
- s.setName("huangshan");
- //上面是Detached,下面新开启Session,因此跟上面没比较,所以全部更新
- Session session1 = sf.getCurrentSession();
- session1.beginTransaction();
- session1.merge(s); // 合并,只更新改过的
- session1.getTransaction().commit();
- }
- @Test
- public void testUpload8() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Query q = session.createQuery("update Student s set s.name='m2' where s.id = 1");
- q.executeUpdate();
- session.getTransaction().commit();
- }
- @Test
- public void testSaveOrUpload9() {
- Teacher t = new Teacher();
- t.setName("t4");
- t.setTitle("ffff");
- t.setYouWifeName("hhh");
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- session.saveOrUpdate(t);
- session.getTransaction().commit();
- t.setName("t5");
- Session session2 = sf.getCurrentSession();
- session2.beginTransaction();
- session2.saveOrUpdate(t);
- session2.getTransaction().commit();
- }
- @Test
- public void testClear() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- System.out.println(s.getName());
- session.clear(); //跟缓存打交道
- Student s1 = (Student)session.get(Student.class, 1);
- System.out.println(s1.getName());
- session.getTransaction().commit();
- }
- @Test
- public void testFlush() {
- Session session = sf.getCurrentSession();
- session.beginTransaction();
- Student s = (Student)session.get(Student.class, 1);
- s.setName("kk");
- session.flush(); //跟数据库打交道
- s.setName("kkkk");
- session.getTransaction().commit();
- }
- @Test
- public void testSchemaExport() { //生成建表语句
- new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
- }
- @AfterClass
- public static void afterClass() {
- sf.close();
- }
- public static void main(String[] args) {
- beforClass();
- }
- }
- hibernate1.2
- hibernate1
- Hibernate1
- hibernate1
- Hibernate1
- Hibernate1
- Hibernate1
- hibernate1
- Hibernate1
- Hibernate1 Xdoclet
- Hibernate1--简介
- hibernate1.1
- Hibernate1(入门)
- Hibernate1基本知识点
- Hibernate1之例子
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hibernate1.user' doesn't exist
- 2
- 2
- sql语句优化之SQL Server
- hibernate1.1
- 第二章 存储器映射
- 命里有时终须有,命里无时莫强求
- 存储过程的分页
- hibernate1.2
- 黑马程序员---枚举的详解
- 利用CSS3特性巧妙实现漂亮的DIV箭头
- Android学习笔记(8)————详细谈谈intent的startActivityForResult()方法
- 发发牢骚
- spring mvc注入配置文件里的属性
- socket编程原理
- 目前人生阶段的关键字
- Oracle 批量导出 Sequence