HIbernate中有save()、persist()、saveOrUpdate()3种方法可以进行保存操作,外加SQL插入语句的执行,总共四种实现插入操作的方式。现在我们就来讲解下它们的使用和区别。
保存操作
-
save()
@Test
public void saveForNew() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("张三");
student.setAge("21");
student.setId("23");
Serializable id_s = session.save(student);
System.out.println(id_s);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
4028bcc267ca6c4d0167ca6c4f360000
Hibernate: insert into Student (AGE, NAME, id) values (?, ?, ?)
save()方法返回Serializable类型的数据库标识符,与数据库里面的值一致。如果实体中有定义主键生成策略,则指定ID的值将无效,但不报错。
@Test
public void saveForGet() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student = session.get(Student.class, "4028bcc267ca6c4d0167ca6c4f360000");
student.setName("wanglaosi3");
session.save(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?
当实体不是新建,而是从数据库获取的持久态数据,save()方法不是执行保存操作,而是更新。
-
persist()
@Test
public void persistForNew() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("张三");
student.setAge("21");
session.persist(student);
System.out.println(student.getId());
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
4028bcc267ca73e20167ca73e4250000
Hibernate: insert into Student (AGE, NAME, id) values (?, ?, ?)
persist()方法没有返回值。
@Test
public void persistForNew() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("张三");
student.setAge("21");
student.setId("22");
session.persist(student);
System.out.println(student.getId());
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
org.hibernate.PersistentObjectException: detached entity passed to persist: com.hibernate.demo.entity.Student
注意:当实体里面有设置主键生成策略时,方法中不能再给实体赋值,否则会报错。
@Test
public void persistForGet() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student = session.get(Student.class, "4028bcc267ca6c4d0167ca6c4f360000");
student.setName("wanglaosi");
session.persist(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?
当实体不是新建,而是从数据库获取的持久态数据,与save()方法一样persist()方法不是执行保存操作,而是更新。
-
insert语句
@Test
public void saveBySql() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
String sql = "insert into Student (id,name,age) values (?,?,?)";
Query query = session.createSQLQuery(sql);
query.setString(0, "22");
query.setString(1, "张三");
query.setString(2, "22");
query.executeUpdate();
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: insert into Student (id,name,age) values (?,?,?)
因为HIbernate里面没有hql新增操作,所以语句操作只有sql。
更新操作
-
update()
@Test
public void updateFromGet() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.load(Student.class, "22");
student.setName("李四");
session.update(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?
注意:如果获取的ID不存在会报错,获取实体的方式不同报错也不相同,后面讲查询操作的时候再详细讲解。
- get()方法报错信息
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
java.lang.NullPointerException
- load()方法报错信息
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.hibernate.demo.entity.Student#22222]
-
update Sql语句
@Test
public void updateBySql() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
String sql = "update Student set name=? where id=?";
Query query = session.createSQLQuery(sql);
query.setString(0, "王五");
query.setString(1, "2222");
query.executeUpdate();
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: update Student set name=? where id=?
注意:sql语句执行update操作,不会验证ID是否存在,所以不会报错。
-
update Hql语句
@Test
public void updateByHql() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
String hql = "update Student set name=? where id=?";
Query query = session.createQuery(hql);
query.setString(0, "赵六");
query.setString(1, "21");
query.executeUpdate();
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
十二月 25, 2018 4:06:24 下午 org.hibernate.hql.internal.ast.HqlSqlWalker generatePositionalParameter
WARN: [DEPRECATION] Encountered positional parameter near line 1, column 62 in HQL: [update com.hibernate.demo.entity.Student set name=? where id=?]. Positional parameter are considered deprecated; use named parameters or JPA-style positional parameters instead.
Hibernate: update Student set NAME=? where id=?
注意:hql语句执行update操作,不会验证ID是否存在,所以不会报错。但是会有一段警告信息。这是因为HIbernate4.1之后对于HQL中查询参数的占位符做了改进,如果仍然用老式的占位符会有类似如下的告警信息。
// 解决updateByHql的占位符警告
@Test
public void updateByHqlWithOutWarn() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
String hql = "update Student set name=:name where id=:id";
Query query = session.createQuery(hql);
query.setParameter("name", "赵四");
query.setParameter("id", "21");
query.executeUpdate();
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: update Student set name=? where id=?
更新保存操作
-
saveOrUpdate()
@Test
public void saveOrUpdateByNew() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("王四33");
student.setAge("21");
student.setId("4028bcc267ca6c4d0167ca6c4f360000");
session.saveOrUpdate("Student", student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
saveOrUpdate方法有2种用户
- 不设置ID值时,执行保存操作。
Hibernate: insert into Student (AGE, NAME, id) values (?, ?, ?)
- 设置ID时,执行更新操作。
Hibernate: update Student set AGE=?, NAME=? where id=?
- 当实体不是新建,而是从数据库获取的持久态数据时,执行更新操作。
@Test
public void saveOrUpdateByGet() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student = session.get(Student.class, "4028bcc267ca6c4d0167ca6c4f360000");
student.setName("王四33");
session.saveOrUpdate("Student", student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?
注意:如果设置的ID在数据库中没有对应数据的时会报错。
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
-
merge()
现在说一个神奇的merge()方法。先来看例子
- 新建实体,不设置ID
@Test
public void mergeForNew_NoId() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setAge("22");
student.setName("wanglaosi3");
session.merge(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: insert into Student (AGE, NAME, id) values (?, ?, ?)
- 新建实体,设置ID,ID不存在
@Test
public void mergeForNew_IdNoExist() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setId("23");
student.setAge("22");
student.setName("wanglaosi3");
session.merge(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: insert into Student (AGE, NAME, id) values (?, ?, ?)
- 新建实体,设置ID,ID存在
@Test
public void mergeForNew_IdExist() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setId("22");
student.setAge("22");
student.setName("wanglaosi3");
session.merge(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?
- 查询实体
@Test
public void mergeForGet() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student = session.get(Student.class, "4028bcc267ca7fa80167ca7faa100000");
student.setName("wanglaosi3");
session.merge(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate: select student0_.id as id1_0_0_, student0_.AGE as AGE2_0_0_, student0_.NAME as NAME3_0_0_ from Student student0_ where student0_.id=?
Hibernate: update Student set AGE=?, NAME=? where id=?