首先说一下在学习Hibernate注解的时候遇到的坑
(1)@Entity@Table(name="xxx")该注解在hibernate4之后就不再使用,否则获取session出错。
hibernate4之后的版本@Entity(name="xxx")
(2)Exception in thread "main" org.hibernate.MappingException: An AnnotationConfiguration instance is required to use <mapping class="XXX"/>
自己在注解书写完成后,一直报这个错,后来在网上查找才知道原来是HibernateUtil.java的问题。
在读取配置文件的时候,hibernate4之后通常使用 configuration= new Configuration().configure();来读取,问题就在这,我们使用的是hibernate3,所以需要修改一下读取配置文件的方法。正确代码是:
configuration= new AnnotationConfiguration().configure();
然后奉上 HibernateUtil.java
package org.hibernate.entity;
import org.hibernate.*;
import org.hibernate.cfg.*;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
// 创建线程局部变量threadLocal,用来保存Hibernate的Session
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
// 使用静态代码块初始化Hibernate
static {
try {
configuration= new AnnotationConfiguration().configure(); // 读取配置文件hibernate.cfg.xml
sessionFactory = configuration.buildSessionFactory(); // 创建SessionFactory
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
// 获得SessionFactory实例
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
// 获得ThreadLocal 对象管理的Session实例.
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
// 通过SessionFactory对象创建Session对象
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
// 将新打开的Session实例保存到线程局部变量threadLocal中
threadLocal.set(session);
}
return session;
}
// 关闭Session实例
public static void closeSession() throws HibernateException {
// 从线程局部变量threadLocal中获取之前存入的Session实例
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
// 重建SessionFactory
public static void rebuildSessionFactory() {
try {
configuration.configure("/hibernate.cfg.xml"); // 读取配置文件hibernate.cfg.xml
sessionFactory = configuration.buildSessionFactory(); // 创建SessionFactory
} catch (Exception e) {
System.err.println("Error Creating SessionFactory ");
e.printStackTrace();
}
}
// 关闭缓存和连接池
public static void shutdown() {
getSessionFactory().close();
}
}
hibernate注解
先上代码,当然使用主键就不需要数据表映射文件了。
package org.hibernate.entity;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="country")
public class Country {
private int id;
private String name;
@Id
@Column(name="id")
@GeneratedValue(generator = "xxx")
@GenericGenerator(name = "xxx", strategy = "native")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Country(String name) {
this.name = name;
}
@Override
public String toString() {
return "Country [id=" + id + ", name=" + name + "]";
}
}
@Entity 指定hibernate映射数据库实体类
@Table(name="country") 指定数据库表名,可以不要
@Id 指定数据库主键,有人把主键映射写在属性上,当然是可以的,但是会破坏类私有属性的封装特性,所以我就写在get方法上。
@Column(name="id") 映射数据库主键列名,如果和属性名一样可以省略
@GeneratedValue(generator = "xxx")
@GenericGenerator(name = "xxx", strategy = "native") 和上一个一起使用指定主键生成策略。
@Basic 指定普通列
@Column(name="name")
Junit测试
package org.hibernate.entity;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.junit.After;
import org.junit.Before;
public class Test {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@org.junit.Test
public void testadd() {
Session session = HibernateUtil.getSession();
session.beginTransaction();
try {
Country a =new Country("USA");
session.save(a);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
}
数据库