hibernate的学习笔记
1.hibernate所需jar包
i.hibernate core
ii./required
iii.slf-nop jar
2.hibernate的配置文件hibernate.cfg.xml
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>
<!-- 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">bjsxt</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> //规定session上线文的 范围,这里规定是在一个线程里,参见15
<!-- 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>//显示生成的sql语句
<property name="format_sql">true</property>//显示生成的sql语句,并进行格式化
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>//让hibernate自动生成建表语句,create,数据库中没有这张表会自动进行创建,update,原来数据库中有这张表,如果表结构修改了,运行程序,数据库表会自动改变,create-drop,当关闭sessionFactory时,数据库中的表会自动被删掉,validte,数据库中的表已经建好,没事往数据库插入数据是,就会和hbm文件进行对照是否一致
<mapping resource="com/bjsxt/hibernate/Student.hbm.xml"/>//告诉hibernate取哪里找对应的表的配置文件
<mapping class="com.bjsxt.hibernate.Teacher"/>
</session-factory>
</hibernate-configuration>
2.hibernate的表的映射文件Strudent.hbm.xml
Student.hbm.xml
<?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>
<class name="com.bjsxt.hibernate.Student" table ="student"> //这里的table="student"可以不用写,因为默认表名和类 //名是一样的,数据库表名是不区分大小写的
<id name="id" column="id"/> //数据库字段名和表的字段名是一样的就不用写column=""
<property name="name" />
<property name="age" />
</class>
</hibernate-mapping>
3.第一个hibernate的小程序
Test.java
package com.bjsxt.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setId(1);
s.setName("zhangsan");
s.setAge(8);
//如果不传参数,hibernate会到src根目录下找hibernate.cfg.xml的配置文件进行读入,如果放在其它目录下或则叫其他 名字的话,就传入路径和文件名,sessionFactory相当于残生connection的工厂
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(s);
session.getTransaction().commit();
}
}
4.用单例模式得到sessionFactory
package com.bjsxt.hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Singleton {
private final static SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory(){
return new Configuration().buildSessionFactory();
}
public SessionFactory getSessionFactory(){
return sessionFactory;
}
}
5.用annotation
在基础类中的属性不加注解,也可以自动就进行映射如下的,name和title,相当于hibernate自动给加上@Basic注解
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>
<!-- 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">bjsxt</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="com/bjsxt/hibernate/Student.hbm.xml"/>
<mapping class="com.bjsxt.hibernate.Teacher"/> //使用annotation要在xml中这么配
</session-factory>
</hibernate-configuration>
基础类Teacher,使用annotation
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.Id;//引入的是javax,是标准里面的接口,jpa
@Entity
@Table(name="_teacher") //当类名和表名不一致的情况
public class Teacher {
private int id;
private String name;
private String title;
private String yourWifeName;
private Date birthDate;
private boolean good;
private Gender gender;
@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;
}
@Enumerated(EnumType.STRING) //对于Enum类型的,通过这个把enum类型转成要存入数据库中字段的类型
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
@Transient //透明的,在数据库中没有对应的字段
public String getYourWifeName() {
return yourWifeName;
}
public void setYourWifeName(String yourWifeName) {
this.yourWifeName = yourWifeName;
}
@Temporal(TemporalType.TIME) //精度,可以规定Date类型的存储,是@Temporal(value =TemporalType.TIME)时,value可以省略,DATE,TIME,TIMESTAMP这几种类型
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}
6. 在hibernate lib 中加入annotation的jar包
a) hibernate annotaion jar
b) ejb3 persistence jar
c) hibernate common-annotations.jar
d) 注意文裆中没有提到hibernate-common-annotations.jar 文件
7.显示建表语句的配置
org.hibernate.tool.hbm2ddl,在记录日志中记录,在log4j的日志系统中记录建表语句
需要加入的jar包:
slf4-api-1.5.8.jar(标准接口包)
log4j-1.2.15.jar(具体实现包)
slf4j-log4j12-1.5.8.jar(slf4j和log4j之间的转换包)
8.hibernate中的java类中的类型,数据库中的类型,映射类型的之间的对应关系
映射类型 java类型 标准sql类型
9.id的生成策略,使用xml配置
Student.hbm.xml
<?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>
<class name="com.bjsxt.hibernate.Student">
<generator class = "uuid"></generator> //native ,identity,sequence,uuid等比较多,用native是让hibernate帮你选
</class>
</hibernate-mapping>
10.使用annotation生成主键
@GeneratorValue //默认使用auto
@GeneratorValue(strategy=GenerationType.IDENTITY) //mysql用的是identiy,oracle用的是sequence
11.为oracle的sequence生成策略指定名字
package com.bjsxt.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.IdClass;
import javax.persistence.SequenceGenerator;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
@Entity
@SequenceGenerator(name="teacherSEQ", sequenceName="teacherSEQ_DB")
public class Teacher {
//private TeacherPK pk;
private int id;
private String name;
private String title;
private String yourWifeName;
private Date birthDate;
private boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
@Transient
public String getYourWifeName() {
return yourWifeName;
}
public void setYourWifeName(String yourWifeName) {
this.yourWifeName = yourWifeName;
}
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="Teacher_GEN")
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;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Temporal(TemporalType.TIME)
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}
11.用table生成主键
package com.bjsxt.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.IdClass;
import javax.persistence.SequenceGenerator;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
@Entity
@javax.persistence.TableGenerator(
name="Teacher_GEN", //生成主键的名字
table="GENERATOR_TABLE", //table名字
pkColumnName = "pk_key", //字段名
valueColumnName = "pk_value", //字段名
pkColumnValue="Teacher", //记录的pkColumnName的名字
allocationSize=1 //增加区间
)
@SequenceGenerator(name="teacherSEQ", sequenceName="teacherSEQ_DB")
@IdClass(TeacherPK.class)
public class Teacher {
//private TeacherPK pk;
private int id;
private String name;
private String title;
private String yourWifeName;
private Date birthDate;
private boolean good;
private Gender gender;
@Enumerated(EnumType.STRING)
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
@Transient
public String getYourWifeName() {
return yourWifeName;
}
public void setYourWifeName(String yourWifeName) {
this.yourWifeName = yourWifeName;
}
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="Teacher_GEN")
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;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Temporal(TemporalType.TIME)
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
/*@EmbeddedId
public TeacherPK getPk() {
return pk;
}
public void setPk(TeacherPK pk) {
this.pk = pk;
}*/
}
12.使用xml生成联合主键
StudentPK .java
package com.bjsxt.hibernate;
import javax.persistence.Embeddable;
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 TeacherPK) {
TeacherPK pk = (TeacherPK)o;
if(this.id == pk.getId() && this.name.equals(pk.getName())) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
}
Student.java
package com.bjsxt.hibernate;
public class Student {
private StudentPK pk;
private int age;
private String sex;
private boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
/*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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public StudentPK getPk() {
return pk;
}
public void setPk(StudentPK pk) {
this.pk = pk;
}
}
Student.hbm.xml
<?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>
<class name="com.bjsxt.hibernate.Student">
<composite-id name="pk" class="com.bjsxt.hibernate.StudentPK">
<key-property name="id"></key-property>
<key-property name="name"></key-property>
</composite-id>
<property name="age" />
<property name="sex" />
<property name="good" type="yes_no"></property>
</class>
</hibernate-mapping>
13.为什么一个对象要写它的equals和hashcode
在内存中,每个对象都被装在hascode表中,当要访问一个对象时会去通过hascode去找这个对象,通过一个hashcode找到的对象可能有几个,这个时候要通过equal来确定唯一的对象
14.使用annotation来实现联合主键,有三种方式
①通过在主键类上注解
package com.bjsxt.hibernate;
import javax.persistence.Embeddable;
@Embeddable
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() {
return this.name.hashCode();
}
}
Student.java
package com.bjsxt.hibernate;
public class Student {
private StudentPK pk;
private int age;
private String sex;
private boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
/*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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@ Id
public StudentPK getPk() {
return pk;
}
public void setPk(StudentPK pk) {
this.pk = pk;
}
}
②把主键类上的注解去掉,在id上加
package com.bjsxt.hibernate;
import javax.persistence.Embeddable;
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() {
return this.name.hashCode();
}
}
Student.java
package com.bjsxt.hibernate;
public class Student {
private StudentPK pk;
private int age;
private String sex;
private boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
/*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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@EmbedId
public StudentPK getPk() {
return pk;
}
public void setPk(StudentPK pk) {
this.pk = pk;
}
}
③在联合主键上加,主键类上 不加
package com.bjsxt.hibernate;
import javax.persistence.Embeddable;
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() {
return this.name.hashCode();
}
}
Student.java
package com.bjsxt.hibernate;
@IdClass(StudentPK.class)
public class Student {
private StudentPK pk;
private int age;
private String sex;
private boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
@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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public StudentPK getPk() {
return pk;
}
public void setPk(StudentPK pk) {
this.pk = pk;
}
}
15.hibernate的核心开发接口
Session session = sessionFactory.openSession(); //每次都创建一个session,需要close()
Session session = sessionFactory.getCurrentSession(); //从上下文找(呼应以上2),如果当前有session就用当前的,如果没有就会重新创建一个session,事物提交会自动close()
16.JTA
java transaction api:针对两个以上的数据库建立事物
17.对象的三种状态
18.几种数据库操作方法
save();
delete();
get();
load();
get()与load()的区别:
①load返回的是代理对象,等到要真正用到对象的内容时才发出sql语句(懒加载)
②直接从数据库加载,不会延迟
19.用xml配置只更新要更新的字段
Student.hbm.xml
<?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>
<class name="com.bjsxt.hibernate.Student" dynamic-update="true">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<property name="age" />
<property name="sex" />
<property name="good" type="yes_no"></property>
</class>
</hibernate-mapping>
20.关于flush()和clear()
clear方法:无论是load还是get,都会首先查找缓存(一级缓存),如果没有才会到数据库找查,调用clear()可以强制清除session缓存
flush()方法:可以强制进行内存到数据库的同步,具体什么时候同步,可以进行设置《
设置方法时,通过session.setFlushMode(FlushMode.……),这个会在性能调优上用到
21.schemaexport,手动生成建表语句
new SchemaExport(new AnnotationConfiguration().configure.create(……,……));//第一个参数时在控制台打印sql语句,第二个是使建表语句到数据库去执行
22.主键关联
两个表的主键互相参照
23.外键关联
一张表里除了主键,还有另外一个主键,然后关联另外一张表里的主键
24.annotation配置单项一对一外键关联
Husband.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class Husband {
private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue
public int getId() {
return id;
}
public String getName() {
return name;
}
@OneToOne
@JoinColumn(name="wifeId")
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;
}
}
25.用xml配置单项一对一外键关联
StuIdCard.hbm.xml
<?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>
<class name="com.bjsxt.hibernate.StuIdCard">
<id name="id">
<generator class="native"></generator>
</id>
<property name="num"/>
<many-to-one name="student" column="studentId" unique="true"></many-to-one>
</class>
</hibernate-mapping>
26.一对一双向外键关联
Husband.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class Husband {
private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue
public int getId() {
return id;
}
public String getName() {
return name;
}
@OneToOne
@JoinColumn(name="wifeId")
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;
}
}
Wife.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Wife {
private int id;
private String name;
private Husband husband;
@OneToOne(mappedBy="wife") //双向一对一外键关联,必须有一方主导,否则会产生冗余数据,例如会有两个wifeid字段
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
@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;
}
}
27.联合主键
WifePK.java
package com.bjsxt.hibernate;
import java.io.Serializable;
public class WifePK implements 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;
}
}
Husband.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.OneToOne;
@Entity
public class Husband {
private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue
public int getId() {
return id;
}
public String getName() {
return name;
}
@OneToOne
@JoinColumns(
{
@JoinColumn(name="wifeId", referencedColumnName="id"),
@JoinColumn(name="wifeName", referencedColumnName="name")
}
) //重命名联合主键
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;
}
}
Wife.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
@Entity
@IdClass(WifePK.class)
public class Wife {
private int id;
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@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;
}
}
28.数据库三范式
①要有主键,列不可分
②联合主键,不能存在部分依赖
③不能存在传递依赖
29.多对一单向关联
User.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_user")
public class User {
private int id;
private String name;
private Group group;
@ManyToOne
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@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;
}
}
Group.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t_group")
public class Group {
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;
}
}
30.一对多的单向关联
group.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="t_group")
public class Group {
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@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;
}
@OneToMany
@JoinColumn(name="groupId")
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
User.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_user")
public class User {
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;
}
}
31.双向一对多和多对一关联
User.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_user")
public class User {
private int id;
private String name;
private Group group;
@ManyToOne
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@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;
}
}
Group.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="t_group")
public class Group {
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@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;
}
@OneToMany(mappedBy="group")
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
32.多对多单向关联
Teacher.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
public class Teacher {
private int id;
private String name;
private Set<Student> students = 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> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
Student.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@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;
}
}
33.双向多对多
Teacher.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
public class Teacher {
private int id;
private String name;
private Set<Student> students = 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> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
Student.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Student {
private int id;
private String name;
private Set<Teacher> teachers = new HashSet<Teacher>();
@ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
@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;
}
}
34.CRUD之C(有关联关系的新增) 双向一对多,多对一
CascadeType对CUD,有用
fetch 对R有用,在多对一的情况下默认设置是EAGER,不仅查询多的一方也会把一的一方发出来,
在一对多的情况下是LAZY,只查出一的一方,不查询多的一方
铁律:①双向关系在程序中要设定双向关系
②双向要设mappedBy
Group.java
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="t_group")
public class Group {
private int id;
private String name;
private Set<User> users = new HashSet<User>();
@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;
}
@OneToMany(mappedBy="group",
cascade={CascadeType.ALL}, //在任何情况下都进行关联,MERGE,在合并的情况下进行关联,PERSIST,REMOVE
fetch=FetchType.EAGER) //对于一的一方,如果进行get查询,会取出一的一方,多的一方不会取,设置Fetch就会进行取了
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
User.java
package com.bjsxt.hibernate;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_user")
public class User {
private int id;
private String name;
private Group group;
@ManyToOne(cascade={CascadeType.ALL})
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@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;
}
}
35.要删除带关联关系的数据
如果想消除关联关系,先设定关系为null.再删除对应记录,如果不删记录,该记录变成垃圾数据或则使用hql
36.继承映射(不太重要)
a)一张总表SINGLE_TABLE
i. hibernate_1900_lnheritence_Mapping_Single_Table
b)每个类分别一张表TABLE_PER_CLASS
i. hibernate_2000_lnheritence_Mapping_Table_Per_Class
c)每个子类一张表jOINED
i. hibernate_2100_lnheritence_Mapping_JOINED
父类上加注解@Inheritance(strategy=InheritanceType.JOINED)
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {... ...}
37.hibernate关于实体类的设计
a)实体类(表)
b)导航(编程方便)
c)确定了编程方式
38.hql
①查询所有
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c where c.name > 'c5'");
List<Category> categories = (List<Category>)q.list();
②带查询条件
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c where c.name > 'c5'");
List<Category> categories = (List<Category>)q.list();
③排序查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c order by c.name desc");
List<Category> categories = (List<Category>)q.list();
④过滤重复
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select distinct c from Category c order by c.name desc");
List<Category> categories = (List<Category>)q.list();
⑤带占位符的查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c where c.id > :min and c.id < :max");
q.setInteger("min", 2);
q.setInteger("max", 8);
List<Category> categories = (List<Category>)q.list();
⑥用?占位符
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c where c.id > ? and c.id < ?");
q.setParameter(0, 2)
q.setParameter(1, 8);
List<Category> categories = (List<Category>)q.list();
⑦分页查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Category c order by c.name desc");
q.setMaxResults(4); //每页的最大页数
q.setFirstResult(2); //起始行数
List<Category> categories = (List<Category>)q.list();
⑧用对象数组取
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select c.id, c.name from Category c order by c.name desc");
List<Object[]> categories = (List<Object[]>)q.list();
for(Object[] o : categories) {
System.out.println(o[0] + "-" + o[1]);
}
⑨查询多对一( //设定fetch type 为lazy后将不会有第二条sql语句)
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Topic t where t.category.id = 1");
List<Topic> topics = (List<Topic>)q.list();
for(Topic t : topics) {
System.out.println(t.getTitle());
//System.out.println(t.getCategory().getName());
}
⑩ 关联查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Msg m where m.topic.category.id = 1");
for(Object o : q.list()) {
Msg m = (Msg)o;
System.out.println(m.getCont());
}
⑪查询结果封装成封装类
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select new com.bjsxt.hibernate.MsgInfo(m.id, m.cont, m.topic.title, m.topic.category.name) from Msg m");
for(Object o : q.list()) {
MsgInfo m = (MsgInfo)o;
System.out.println(m.getCont());
}
⑫联合查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select t.title, c.name from Topic t join t.category c "); //join Category c
for(Object o : q.list()) {
Object[] m = (Object[])o;
System.out.println(m[0] + "-" + m[1]);
}
⑬只去单个对象
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Msg m where m = :MsgToSearch "); //不重要
Msg m = new Msg();
m.setId(1);
q.setParameter("MsgToSearch", m);
Msg mResult = (Msg)q.uniqueResult();
⑭使用聚合函数
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select count(*) from Msg m");
long count = (Long)q.uniqueResult();
⑮使用函数
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select max(m.id), min(m.id), avg(m.id), sum(m.id) from Msg m");
Object[] o = (Object[])q.uniqueResult();
System.out.println(o[0] + "-" + o[1] + "-" + o[2] + "-" + o[3]);
⑯其他
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Msg m where m.id between 3 and 5");
for(Object o : q.list()) {
Msg m = (Msg)o;
System.out.println(m.getId() + "-" + m.getCont());
}
⑰其他
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Msg m where m.id in (3,4, 5)");
for(Object o : q.list()) {
Msg m = (Msg)o;
System.out.println(m.getId() + "-" + m.getCont());
}
⑱是不是Null
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Msg m where m.cont is not null");
for(Object o : q.list()) {
Msg m = (Msg)o;
System.out.println(m.getId() + "-" + m.getCont());
}
⑳集合是不是空
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Topic t where t.msgs is empty");
for(Object o : q.list()) {
Topic t = (Topic)o;
System.out.println(t.getId() + "-" + t.getTitle());
}
(21)模糊查询
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Topic t where t.title like '%5'");
for(Object o : q.list()) {
Topic t = (Topic)o;
System.out.println(t.getId() + "-" + t.getTitle());
}
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("from Topic t where t.title like '_5'");
for(Object o : q.list()) {
Topic t = (Topic)o;
System.out.println(t.getId() + "-" + t.getTitle());
}
(22)函数
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select lower(t.title)," +
"upper(t.title)," +
"trim(t.title)," +
"concat(t.title, '***')," +
"length(t.title)" +
" from Topic t ");
for(Object o : q.list()) {
Object[] arr = (Object[])o;
System.out.println(arr[0] + "-" + arr[1] + "-" + arr[2] + "-" + arr[3] + "-" + arr[4] + "-");
}
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select abs(t.id)," +
"sqrt(t.id)," +
"mod(t.id, 2)" +
" from Topic t ");
for(Object o : q.list()) {
Object[] arr = (Object[])o;
System.out.println(arr[0] + "-" + arr[1] + "-" + arr[2] );
}
(23)时间
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select current_date, current_time, current_timestamp, t.id from Topic t");
for(Object o : q.list()) {
Object[] arr = (Object[])o;
System.out.println(arr[0] + " | " + arr[1] + " | " + arr[2] + " | " + arr[3]);
}
(24)group by
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select t.title, count(*) from Topic t group by t.title") ;
for(Object o : q.list()) {
Object[] arr = (Object[])o;
System.out.println(arr[0] + "|" + arr[1]);
} //group by 的字段必须在select中
(25)having
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("select t.title, count(*) from Topic t group by t.title having count(*) >= 1") ;
for(Object o : q.list()) {
Object[] arr = (Object[])o;
System.out.println(arr[0] + "|" + arr[1]);
} //having 后面必须是聚合函数
(26) exists
//用in 可以实现exists的功能
//但是exists执行效率高
@Test
public void testHQL_31() {
Session session = sf.openSession();
session.beginTransaction();// t.id not in (1)
Query q = session.createQuery("from Topic t where not exists (select m.id from Msg m where m.topic.id=t.id)") ;
// Query q = session.createQuery("from Topic t where exists (select m.id from Msg m where m.topic.id=t.id)") ;
for(Object o : q.list()) {
Topic t = (Topic)o;
System.out.println(t.getTitle());
}
session.getTransaction().commit();
session.close();
}
(27)//update and delete
//规范并没有说明是不是要更新persistent object,所以如果要使用,建议在单独的trasaction中执行
@Test
public void testHQL_32() {
Session session = sf.openSession();
session.beginTransaction();
Query q = session.createQuery("update Topic t set t.title = upper(t.title)") ;
q.executeUpdate();
q = session.createQuery("from Topic");
for(Object o : q.list()) {
Topic t = (Topic)o;
System.out.println(t.getTitle());
}
session.createQuery("update Topic t set t.title = lower(t.title)")
.executeUpdate();
session.getTransaction().commit();
session.close();
}
(28)//Native(了解)
Session session = sf.openSession();
session.beginTransaction();
SQLQuery q = session.createSQLQuery("select * from category limit 2,4").addEntity(Category.class); //返回的泛型
List<Category> categories = (List<Category>)q.list();
for(Category c : categories) {
System.out.println(c.getName());
}
39.面试题之java有内存泄漏吗?
语法级别没有 但是可由java引起,例如:连接池不关闭,或io读取后不关闭,java调用c,c调用windows的文件打开
40.面试题之1+N问题
问题描述:当两个实体类有关联关系时,我只想取出其中一个实体类的对象,因为设成了EAGER,所有在取得
时候会连带着另外一个实体类的对象一起从数据库中取出来
解决办法:
a)@ManyToOne(fetch=FetchType.LAZY)
//fetch=FetchType.LAZY 解决N+1问题 说明如下:
//当多对一(@ManyToOne)已经设定属性" fetch=FetchType.LAZY "时
//只有当需要时(如:t.getCategory().getName()时)才会去获取关联表中数据 可以解决N+1问题
b)join fetch
//join fetch 解决N+1问题 说明如下:
//修改hql语句为--" from Topic t left join fetch t.category c "
41.面试题之用list和iteration取得区别
a)list取所有
b)iterate先取 ID,等用到的时候再根据ID来取对象
c)session中list第二次发出,仍会到数据库査询
d)iterate 第二次,首先找session 级缓存
42.一级和二级缓存
session是一级缓存
SessionFactory二级缓存
a)load默认使用二级缓存,iterate默认使用二级缓存
b)list默认往二级缓存加数据,但是查询的时候不使用,查询缓存除外(相同的sql查询)
二级缓存的设置
注:使用EhCache二级缓存 需要导入ehcache-1.2.3.jar及commons-logging-1.0.4.jar包
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>
<!-- 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>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="cache.use_query_cache">true</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/bjsxt/hibernate/Group.hbm.xml"/>
<mapping resource="com/bjsxt/hibernate/User.hbm.xml"/>
-->
<mapping class="com.bjsxt.hibernate.Category"/>
<mapping class="com.bjsxt.hibernate.Msg"/>
<mapping class="com.bjsxt.hibernate.Topic"/>
</session-factory>
</hibernate-configuration>
ehcache.xml
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000" //可以装载的最大对象数
eternal="false" //永远存在
timeToIdleSeconds="120" //对象可以不被使用停留的时间
timeToLiveSeconds="1200" //对象的生命周期
overflowToDisk="true" //当内存满了以后写到硬盘
memoryStoreEvictionPolicy = "LRU" //使用哪种缓存算法
/>
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
memoryStoreEvictionPolicy = "LRU"
/>
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
<!-- Place configuration for your caches following -->
</ehcache>
Category.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
//@BatchSize(size=5)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region ="sampleCache1")//第一个参数设置缓存可以读写,第二个参数设置使用哪个配置的缓存
public class Category {
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;
}
}
43.使用查询缓存的设置(相同的查询)
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>
<!-- 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>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="cache.use_query_cache">true</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/bjsxt/hibernate/Group.hbm.xml"/>
<mapping resource="com/bjsxt/hibernate/User.hbm.xml"/>
-->
<mapping class="com.bjsxt.hibernate.Category"/>
<mapping class="com.bjsxt.hibernate.Msg"/>
<mapping class="com.bjsxt.hibernate.Topic"/>
</session-factory>
</hibernate-configuration>
//join fetch
@Test
public void testQueryCache() {
Session session = sf.openSession();
session.beginTransaction();
List<Category> categories = (List<Category>)session.createQuery("from Category")
.setCacheable(true).list();
session.getTransaction().commit();
session.close();
Session session2 = sf.openSession();
session2.beginTransaction();
List<Category> categories2 = (List<Category>)session2.createQuery("from Category")
.setCacheable(true).list();
session2.getTransaction().commit();
session2.close();
}
44.缓存算法
a)缓存算法:(纯为了面试)
i. LRU LFU FIFO
1.Least Recently Used –最近很少被使用
2.Least Frequently Used(命中率高低)
3.First In First Out 按顺序替换
ii. memoryStoreEvictionPolicy = "LRU"
(ehcache.xml中配置)
45.集中有关事务的问题
①脏读(dirty read)
读取别人还没提交的事物
②不可重复读(non-repeatable read)
别人已经提交了事物,我这边更新,发现和前面的数据不一样了(针对更新)
③幻读(phantom read)
别人插入了数据,我读的结果和上次不一样(针对插入)
1 事务并发处理(面试的意义更大)
a)事务:ACID
i.Atomic Consistency Itegrity Durability
b)事务并发时可能出现的问题:
第一类丢失更新(Lost Update)
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询账户余额为1000元 |
|
T4 |
|
查询账户余额为1000元 |
T5 |
|
汇入100元把余额改为1100元 |
T6 |
|
提交事务 |
T7 |
取出100元把余额改为900 元 |
|
T8 |
撤销事务 |
|
T9 |
余额恢复为1000元(丢失更新) |
|
dirty read脏读(读到了另一个事务在处理中还未提交的数据)
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
|
查询账户余额为1000元 |
T4 |
|
汇入100元把余额改为1100元 |
T5 |
查询账户余额为1100元(读取脏数据) |
|
T6 |
|
回滚 |
T7 |
取款1100 |
|
T8 |
提交事务失败 |
|
non-repeatable read 不可重复读
时间 |
取款事务A |
存款事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询账户余额为1000元 |
|
T5 |
|
汇入100元把余额改为1100元 |
T5 |
|
提交事务 |
T6 |
查询帐户余额为1100元 |
|
T8 |
提交事务 |
|
second lost update problem 第二类丢失更新(不可重复读的特殊情况)
时间 |
取款事务A |
存款事务B |
T1 |
|
开始事务 |
T2 |
开始事务 |
|
T3 |
|
查询账户余额为1000元 |
T4 |
查询账户余额为1000元 |
|
T5 |
|
取出100元把余额改为900元 |
T6 |
|
提交事务 |
T7 |
汇入100元 |
|
T8 |
提交事务 |
|
T9 |
把余额改为1100元(丢失更新) |
|
phantom read 幻读
时间 |
查询学生事务A |
插入新学生事务B |
T1 |
开始事务 |
|
T2 |
|
开始事务 |
T3 |
查询学生为10人 |
|
T4 |
|
插入1个学生 |
T5 |
查询学生为11人 |
|
T6 |
|
提交事务 |
T7 |
提交事务 |
|
c)数据库的事务隔离机制
i. 查看 java.sql.Connection 文档
ii. 1:read-uncommitted 2:read-committed 4:repeatable read 8:serializable(数字代表对应值)
为什么取值要使用 1 2 4 8 而不是 1 2 3 4
1=0000 2=0010 4=0100 8=1000(位移计算效率高)
1.只要数据库支持事务,就不可能出现第一类丢失更新
2.read-uncommitted(允许读取未提交的数据) 会出现dirty read, phantom-read,
non-repeatable read 问题
3.read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirty read,因为只有另
一个事务提交才会读出来结果,但仍然会出现 non-repeatable read 和 phantom-read
使用read-commited机制可用悲观锁 乐观锁来解决non-repeatable read 和 phantom-read问题
4.repeatable read(事务执行中其他事务无法执行修改或插入操作 较安全)
5.serializable解决一切问题(顺序执行事务 不并发,实际中很少用)
46.悲观锁和乐观锁
悲观锁:当前被更新的数据被我锁定,谁都不能更改,直到我更改完以后,解锁了,别人才可以更改
乐观锁:我和别人都可以更改,在我更改的时候,重新到数据库查询这条数据还是不是原来的那条,如果不是,重新再查一次,进行更新,一般会用
update_time或则version字段来实现
在hibernate中的设置
a)设定hibernate的事务隔离级别(使用hibernate.connection.isolation配置 取值1、2、4、8)
i. hibernate.connection.isolation = 2(如果不设 默认依赖数据库本身的级别)
ii. 用悲观锁解决repeatable read的问题(依赖于数据库的锁)
①使用悲观锁
@Test
public void testPessimisticLock() {
Session session = sf.openSession();
session.beginTransaction();
Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE);
int balance = a.getBalance();
//do some caculation
balance = balance - 10;
a.setBalance(balance);
session.getTransaction().commit();
session.close();
}
②使用乐观锁
Account.java
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Version;
@Entity
public class Account {
private int id;
private int balance;
private int version;
@Version
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
47.知识点重要程程度总结