JavaEE学习笔记之SSH—Hibernate(3)
hibernate2016-07-05
封装HibernateSessionFactory
因为Session是线程不安全的,为了保证当前线程只有一个session对象,并且当前线程中的Session不能让其他线程来访问,需要将获取Session的方法进行封装,为了保证Session的线程安全性,需要将Session放到ThreadLocal中。
ThreadLocal为线程本地变量
封装过程:(非常重要)
public class HibernateSessionFactory {
private static String configFile ="/hibernate.cfg.xml";
//声明一个线程本地变量,用来存放当前中的Session,保证不让其他线程访问到
private static ThreadLocal<Session> threadLocal = new ThreadLocal<>();
private static Configuration config = new Configuration();
private static SessionFactory sessionFactory;
static {
//读取配置文件
config.configure(configFile);
//创建sessionFactory
sessionFactory = config.buildSessionFactory();
}
//获取session
public static Session getSession() {
/*当获取Session的时候先到当前线程的本地变量中寻找,如果有直接返回,
*如果没有或者当前线程已经关闭需要重新开启一个Session
*,返回,并且放到当前线程中
*/
Session session = threadLocal.get();
if(session == null || !session.isOpen()){
session =(sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
//关闭session
public static void close(){
/*
*关闭的时候先到当前线程中的本地变量中拿到session,如果可以取到,直接关闭
*最后将本地变量清空
*/
Session session = threadLocal.get();
threadLocal.set(null);
if(session!=null){
session.close();
}
}
}
下面来看看学习Hibernate框架比较难的一部分——关联关系映射。
首先关联关系分为三种:
1.一对一
2.一对多
3.多对多
映射一对一关联:
有两种方式:
a.通过主键来映射(就是让从表的主键和主表的主键一样就可以)
b.通过外键
映射一对多关联:
映射多对多关联:
两种方式:
a.双方配置<many-to-many />,借助于桥表
b.生成中间表,拆分成两个<one-to-many />
a.
b.
当然还有一种情况就是继承关系的映射 –>有三种方式:
1.每个类一张表
2.一个类域一张表
3.每个子类一张表
第一种方式
.
第二种方式
第三种方式
实例:
Animal.java
public class Animal {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return ",id=" + id + ", name=" + name + "]";
}
}
Dog.java
public class Dog extends Animal{
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Dog [color=" + color + super.toString() +"]";
}
}
Bird.java
public class Bird extends Animal{
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Bird [type=" + type + super.toString() +"]";
}
}
第一种方式的映射文件(inherit_per_class.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.briup.day05.inherit">
<class name="Animal" table="tbl_animal">
<id name="id" column="id">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
<!-- 以上是配置父类的基本属性,需要指定父类使用的表名-->
<!-- 以上是配置子类的配置,需要指定子类使用的表名,使用joined-subclass来和父类关联,
key值继承父类的,column指定子类在表中的主键;property为子类特有的属性-->
<joined-subclass name="Dog" table="tbl_dog">
<key column="d_id"/>
<property name="color"/>
</joined-subclass>
<joined-subclass name="Bird" table="tbl_bird">
<key column="b_id"/>
<property name="type"/>
</joined-subclass>
</class>
</hibernate-mapping>
第二种方式的映射文件(inherit_one_class.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.briup.day05.inherit">
<class name="Animal" table="tbl_allclass">
<id name="id" column="id">
<generator class="uuid.hex">
</generator>
</id>
<!-- discriminator用来指定标识列 -->
<discriminator column="a_value" />
<property name="name" />
<!-- discriminator-value用来指定标识列中应该填入的值, 用这个值来区分这条记录是属于哪个类的,property用来指明子类特有的属性 -->
<subclass name="Dog" discriminator-value="dog">
<property name="color" />
</subclass>
<subclass name="Bird" discriminator-value="bird">
<property name="type" />
</subclass>
</class>
</hibernate-mapping>
第三种方式的映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.briup.day05.inherit">
<class name="Animal" abstract="true">
<id name="id" column="id">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
<union-subclass name="Dog" table="tbl_dog">
<property name="color"/>
</union-subclass>
<union-subclass name="Bird" table="tbl_bird">
<property name="type"/>
</union-subclass>
</class>
</hibernate-mapping>
Hibernate配置文件(hibernate.cfg.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/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://127.0.0.1:3306/ssh</property>
<property name="connection.username">root</property>
<property name="connection.password">root</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>
<!-- 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/briup/day05/inherit/inherit_per_class.hbm.xml" /> -->
<!-- <mapping resource="com/briup/day05/inherit/inherit_son_class.hbm.xml" /> -->
<!--<mapping resource="com/briup/day05/inherit/inherit_one_class.hbm.xml" /> -->
</session-factory>
</hibernate-configuration>
这些都配置好后,你就可以测试三种方式了,随便选择一个映射文件,测试类中代码不需要变即可测试。
测试类Test.java
public class Test {
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.beginTransaction();
Dog dog = new Dog();
dog.setColor("金黄色");
dog.setName("一休");
Bird bird = new Bird();
bird.setType("八哥");
bird.setName("汪汪");
session.save(bird);
session.save(dog);
transaction.commit();
Transaction transaction2 = session.beginTransaction();
String hql = "from Dog where name=?";
Dog dog1 = (Dog) session.createQuery(hql)
.setString(0, "一休")
.uniqueResult();
System.out.println(dog1);
transaction2.commit();
}
}
这里演示第一种方式的效果
结果: