Hibernate(5)session的方法 |
您所在的位置:网站首页 › hibernate的save方法捕捉不到异常 › Hibernate(5)session的方法 |
1. Session缓存 Session缓存(Hibernate一级缓存),在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存。只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期。
Session 缓存可减少 Hibernate 应用程序访问数据库的频率。
两次获取同一个对象:
①第一次获取Users对象时会去数据库中查找,找到之后把Users对象的引用赋给user引用变量,同时还会把Users对象的引用给到Session缓存中,
②若再次查找同一个Users变量,首先会去Session中找有没有,若缓存中有就不去查询数据库,直接从缓存中获取
/**
* Session缓存(Hibernate一级缓存),在 Session 接口的实现中包含一系列的 Java 集合,
*这些 Java 集合构成了 Session 缓存。
*只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期
*Session 缓存可减少 Hibernate 应用程序访问数据库的频率。
* 两次获取同一个对象:
* ①第一次获取Users对象时会去数据库中查找,找到之后把Users对象的引用赋给user引用变量,
* 同时还会把Users对象的引用给到Session缓存中,
* ②若再次查找同一个Users变量,首先会去Session中找有没有,若缓存中有就不去查询数据库,直接从缓存中获取
*/
@Test
public void testSessionCache(){
Users user = (Users) session.get(Users.class, 8);
System.out.println(user);
Users user2 = (Users) session.get(Users.class, 8);
System.out.println(user2);
}
2. flush方法:使数据表中的记录和Session缓存中的对象的状态保持一致,为保持一致,则可能会发送对应的SQL语句
* 提下情况会调用该方法:
* 1.在Transaction的commit方法中,先调用session的Flush方法,在提交事务
* 2.显式的调用flush()方法可能会发送SQL语句,但不会提交事务
* 3.注意:在未提交事务或显式的调用session.flush()方法之前,也有可能进行flush()操作。
* ①.执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新的记录
* ②.若记录的ID是由底层数据库使用自增的方式生成的则在调用save()方法后,就会立即发送INSERT语句,因为save方法后
* 必须保证对象的ID是存在的
/**
* flush方法:使数据表中的记录和Session缓存中的对象的状态保持一致,为保持一致,则可能会发送对应的SQL语句
*提下情况会调用该方法:
* 1.在Transaction的commit方法中,先调用session的Flush方法,在提交事务
* 2.显式的调用flush()方法可能会发送SQL语句,但不会提交事务
* 3.注意:在未提交事务或显式的调用session.flush()方法之前,也有可能进行flush()操作。
* ①.执行HQL或QBC查询,会先进行flush()操作,以得到数据表的最新的记录
* ②.若记录的ID是由底层数据库使用自增的方式生成的则在调用save()方法后,就会立即发送INSERT语句,因为save方法后
*必须保证对象的ID是存在的
*/
@Test
public void testSessionFlush(){
Users users = (Users) session.get(Users.class, 8);
users.setLoginName("Jack");
//session.flush();
//System.out.println("flush()");
//HQL查询
Users user2 = (Users) session.createCriteria(Users.class).uniqueResult();
System.out.println(user2);
}
//使用save()方法,会立即执行SQL语句,而不用等到事务提交,其他方法需要等到事务提交之后到能执行SQL语句
@Test
public void testSessionFlush2(){
Users user = new Users("mengqi", "123", "孟奇", "河南省郑州市", "19843244908", "[email protected]", new Date());
session.save(user);
}
3. reflush():获取数据表中最新的记录,该方法会强制执行查询,
* 手动修改表中的记录,使用reflush(),再次打印user时,打印的记录就会和之前打印的不一致,此时打印的是手动修改后的记录,即最新是记录,若打印的不是最新的则是MYSQL数据库的隔离级别问题,MYSQL默认的隔离级别为REPEATABLE READ(可重复读),需要改成READ COMMITED(读已提交)。
* 在Hibernate的配置文件中,可以显示的设置隔离级别,每一个隔离级别都对应一个数字
* 1对应READ UNCOMMITED
* 2对应READ COMMITED
* 4对应REPEATABLE READ
* 8对应SERIALIZEABLE
*Hibernate通过Hibernate配置文件指定,Hibernate.connection.isolation属性设置事务的隔离级别
/**
* reflush():获取数据表中最新的记录,该方法会强制执行查询,
* 手动修改表中的记录,使用reflush(),再次打印user时,打印的记录就会和之前打印的不一致,此时打印
* 的是手动修改后的记录,即最新是记录,若打印的不是最新的则是MYSQL数据库的隔离级别问题,
* MYSQL默认的隔离级别为REPEATABLE READ(可重复读),需要改成READ COMMITED(读已提交)
* 在Hibernate的配置文件中,可以显示的设置隔离级别,每一个隔离级别都对应一个数字
* 1对应READ UNCOMMITED
* 2对应READ COMMITED
* 4对应REPEATABLE READ
* 8对应SERIALIZEABLE
*Hibernate通过Hibernate配置文件指定,Hibernate.connection.isolation属性设置事务的隔离级别
*/
@Test
public void testReFlush(){
Users user = (Users) session.get(Users.class, 8);
System.out.println(user);
//在此打印断点,打印出的user与上一个打印的user没有什么不同
System.out.println(user);
//此时手动修改了表中的记录,使用reflush(),再次打印user时,打印的记录就会和之前打印的不一致,此时打印
//的是手动修改后的记录,即最新是记录,若打印的不是最新的则是MYSQL数据库的隔离级别问题,
//MYSQL默认的隔离级别为REPEATABLE READ(可重复读),需要改成
session.refresh(user);
System.out.println(user);
}
4. claer():清理缓存,两次查询同一条记录,中间使用clear()清理之后,第二条查询也会发送一条记录
/**
* claer():清理缓存,两次查询同一条记录,中间使用clear()清理之后,第二条查询也会发送一条记录
*/
@Test
public void testClear(){
Users users = (Users) session.get(Users.class, 8);
session.clear();
Users users2 = (Users) session.get(Users.class, 8);
}
5. save()
* ①把对象加入到Session缓存中,使一个临时对象变为持久化对象
* ②选用映射文件指定的标识符生成器,为对象分配ID
* ③在flush()缓存时会发送一条INSERT语句
* ④在save()方法之前设置ID属性值是无效的,但不抛出异常
* ⑤持久化对象的ID是不能被修改的
/**
* save():
* ①把对象加入到Session缓存中,使一个临时对象变为持久化对象
* ②选用映射文件指定的标识符生成器,为对象分配ID
* ③在flush()缓存时会发送一条INSERT语句
* ④在save()方法之前设置ID属性值是无效的,但不抛出异常
* ⑤持久化对象的ID是不能被修改的
*/
@Test
public void testSave(){
Users user = new Users("wangqiang", "123", "王强", "河南省", "18292389876", "[email protected]", new Date());
//save()方法前后的对象区别在于save()之后会给对象分配ID
System.out.println("user:"+user);
session.save(user);
System.out.println("user:"+user);
//在save()方法前修改ID是无效的
Users user2 = new Users("wangqiang", "1234", "王强", "河南省", "18292389876", "[email protected]", new Date());
user2.setId(100);
session.save(user2);
System.out.println("user2:"+user2);//为id赋值失败
user2.setId(100);
}
6. Persist():也会执行INSERT操作,作用与save()一致
与save的主要内容区别:
persist把一个瞬态的实例持久化,但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。
save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert
/**
* Persist():也会执行INSERT操作,作用与save()一致,与save的主要内容区别:
persist把一个瞬态的实例持久化,但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。
save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert
*:
*/
@Test
public void testPersist(){
Users user = new Users("wangwei", "123", "王伟", "河南省", "19483928495", "[email protected]", new Date());
user.setId(100);
session.persist(user);
}
7. GET()和Load()的区别
* 1.get方法会立即加载该对象,立即执行查询
* load方法,若不使用该对象,则不会立即加载,而返回一个代理对象,不会立即执行查询操作
* 2.若数据表中没有对应的记录get返回null,load会抛出异常
* 3.load方法可能会抛出懒加载异常,因为load方法是在使用对象的时候再执行查询操作,
* 假如在使用对象之前把session关闭,即需要初始化代理对象之前已经关闭了Session,同时又在使用加载的对象,
* 就会出现懒加载异常,若不使用加载的对象,则没有问题
* get在使用对象之前关闭session则没有问题。
* GET()和Load()的区别
* 1.get方法会立即加载该对象,立即执行查询
* load方法,若不使用该对象,则不会立即加载,而返回一个代理对象,不会立即执行查询操作
* 2.若数据表中没有对应的记录get返回null,load会抛出异常
* 3.load方法可能会抛出懒加载异常,因为load方法是在使用对象的时候再执行查询操作,
* 假如在使用对象之前把session关闭,即需要初始化代理对象之前已经关闭了Session,同时又在使用加载的对象,
* 就会出现懒加载异常,若不使用加载的对象,则没有问题
* get在使用对象之前关闭session则没有问题。
*
*/
@Test
public void testGet(){
Users user = (Users) session.get(Users.class, 5);
session.close();
System.out.println(user);
}
@Test
public void testLoad(){
Users user = (Users) session.load(Users.class, 5);
session.close();//使用对象前关闭session,出现懒加载异常org.hibernate.LazyInitializationException,不使用则没有问题
System.out.println(user);
}
8. Update()
* 1.若更新一个持久化对象,不需要显示的调用update()方法,因为在调用Transaction的commit方法时,会先执行
*Session的flush()方法
* 2.更新一个游离对象时,需要显式的调用Session的update方法,可以把一个游离对象变为一个持久化对象
*注意:
* ①.若显式的调用Session的update方法,则无论游离的对象中属性有没有变化,都会发送update语句
*可以使用Xxx.hbm.xml文件的class节点设置select-before-update=true(默认为false),
*但通常并不设置此属性
* ②.若数据表中没有对应的记录,但还调用了update方法,会抛出异常
* ③.当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象,
* 会抛出异常
/**
* Update()
* 1.若更新一个持久化对象,不需要显示的调用update()方法,因为在调用Transaction的commit方法时,会先执行
*Session的flush()方法
* 2.更新一个游离对象时,需要显式的调用Session的update方法,可以把一个游离对象变为一个持久化对象
*注意:
* ①.若显式的调用Session的update方法,则无论游离的对象中属性有没有变化,都会发送update语句
*可以使用Xxx.hbm.xml文件的class节点设置select-before-update=true(默认为false),
*但通常并不设置此属性
* ②.若数据表中没有对应的记录,但还调用了update方法,会抛出异常
* ③.当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象,
* 会抛出异常
*/
@Test
public void testUpdate(){
Users user = (Users) session.get(Users.class, 8);
//1.
transaction.commit();
//关闭session,user对象成为游离对象
session.close();
//②更改游离对象的id,使update方法更新一个数据库中不存在的记录,结果是抛出异常
//user.setId(100);
//虽然又开启了一个Session,但是这个Session与上一个Session并没有联系。
session = sessionFactory.openSession();
transaction = session.beginTransaction();
//③虽然这只是一个简单的查询,但是执行查询会在session缓存中关联ID为8的一个持久化对象,
//当显式执行下面的update方法时,会把id为8的游离对象也关联到session缓存中,但是Session缓存中不能有
//两个相同ID的对象
Users users = (Users) session.get(Users.class, 8);
user.setLoginName("Nick");
//2.只有显式的调用session的update方法才能让设置的LoginName属性生效
session.update(user);
}
9. SaveOrUpdate():若是一个临时对象则执行save,游离对象执行update
* 注意:
* 1.若OID不为null,但数据表中没有与之对应的记录则会抛出异常,因为虽然OID不为空,也是一个游离对象,
*但是数据表中没有对应的记录无法执行update语句。
* 2.了解:OID值等于id的unsaved-value属性值的对象,也被认为是一个游离对象,unsave-value是映射文件中id子节点的属性
/**
* SaveOrUpdate():若是一个临时对象则执行save,游离对象执行update
* 注意:
* 1.若OID不为null,但数据表中没有与之对应的记录则会抛出异常,因为虽然OID不为空,也是一个游离对象,
*但是数据表中没有对应的记录无法执行update语句。
* 2.了解:OID值等于id的unsaved-value属性值的对象,也被认为是一个游离对象,unsave-value是映射文件中id子节点的属性
*/
@Test
public void testSaveOrUpdate(){
//临时对象,调用saveOrUpdate()方法,执行insert语句
Users user = new Users("wangmei", "123", "王梅", "河南省", "19483928495", "[email protected]", new Date());
//设置id为8对应数据库表中存在的记录,调用saveOrUpdate()方法,执行update语句
user.setId(8);
//该值等于映射文件中id子节点的unsave-value属性值,所以可以调用saveOrUpdate()方法,执行insert语句
user.setId(100);
session.saveOrUpdate(user);
}
10. Delete():Session的delete()方法既可以删除一个游离对象,又可以删除一个持久化对象,
* ①只要OID和数据表中一条记录对应,就会准备执行Delete操作,若OID在数据表中没有对应的记录,则会抛出异常。
* ②可以通过设置Hibernate配置文件中的一个hibernate.use_identifier_rollback 属性
*来把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象
/**
* Delete():Session的delete()方法既可以删除一个游离对象,又可以删除一个持久化对象,
* ①只要OID和数据表中一条记录对应,就会准备执行Delete操作,若OID在数据表中没有对应的记录,则会抛出异常。
* ②可以通过设置Hibernate配置文件中的一个hibernate.use_identifier_rollback 属性
*来把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象
*/
@Test
public void testDelete(){
//因为数据表中id为8的记录已经被删除了,所以该对象是游离对象
// Users user = new Users();
// user.setId(8);
//持久化对象也可以删除
Users user = (Users) session.get(Users.class, 7);
session.delete(user);
//执行完delete之后,该对象还是有ID值的,若之后想要对该对象执行saveOrUpdate方法,则会强制发送update语句
//但是,数据表中已经没有这条记录,就会抛异常
System.out.println(user);
}
11. Evict():从Session中把指定的持久化对象移除
/**
* Evict():从Session中把指定的持久化对象移除
*
*/
@Test
public void testEvict(){
Users user = (Users) session.get(Users.class, 4);
Users user2 = (Users) session.get(Users.class, 5);
user.setLoginName("Lucy");
user2.setLoginName("Jack");
//虽然更新了两个对象的值,但是由于user对象从session中移除,所以只对user2执行了update
session.evict(user);
}
12. doWork():调用存储过程,需要获取Connection
/**
* doWork():调用存储过程,需要获取Connection
*/
@Test
public void testDoWork(){
session.doWork(new Work() {
@Override
public void execute(Connection conn) throws SQLException {
//没有配置C3P0数据源时连接是从数据库中获取的:com.mysql.jdbc.JDBC4Connection@42f92dbc
//配置C3P0数据源之后从连接池中获取连接:com.mchange.v2.c3p0.impl.NewProxyConnection@66ee2542
System.out.println(conn);
//调用存储过程
}
});
}
13. dynamic-update:class节点的属性不设置的话执行更新操作的话,会更新全部的属性值,设置之后仅更新修改后的属性值
*好处:减少数据库的操作
/**
* dynamic-update:class节点的属性,不设置的话执行更新操作的话,会更新全部的属性值,设置之后仅更新修改后的属性值
*好处:减少数据库的操作
*/
@Test
public void testdynamicUpdate(){
Users user = (Users) session.get(Users.class, 4);
user.setLoginPwd("1234");
}
14. 主键生成策略:increment主键生成器时会出现并发的问题,连续执行两次该方法,模仿两个线程同时访问同一个数据表
* 由于是自增,但是是两个线程,所以会造成两个线程的id自增之后,id值重复,无法执行SQL语句
/**
* 主键生成策略:increment主键生成器时会出现并发的问题,连续执行两次该方法,模仿两个线程同时访问同一个数据表
* 由于是自增,但是是两个线程,所以会造成两个线程的id自增之后,id值重复,无法执行SQL语句
* @throws InterruptedException
*/
@Test
public void testIdGenerator() throws InterruptedException{
Users user = new Users("wangwei", "123", "王伟", "河南省", "19483928495", "[email protected]", new Date());
session.save(user);
//Thread.sleep(5000);
}
15. ①派生属性②Java 时间和日期类型的 Hibernate 映射
/**
* ①派生属性
* ②Java 时间和日期类型的 Hibernate 映射
*/
@Test
public void testPropertyUpdate(){
Users user = (Users) session.get(Users.class, 1);
user.setLoginName("AAA");
System.out.println(user.getDesc());
System.out.println(user.getDate().getClass());
}
16. 大文件属性映射
/**
* 大文件属性映射数据库
* @throws Exception
*/
@Test
public void testBlob() throws Exception{
Users user = new Users("wangwei", "123", "王伟", "河南省", "19483928495", "[email protected]", new Date());
user.setContent("CONTENT");
//文件的输入流
InputStream inputStream = new FileInputStream("1.jpg");
Blob image = Hibernate.getLobCreator(session).createBlob(inputStream, inputStream.available());
user.setImage(image);
session.save(user);
Users user2 = (Users) session.get(Users.class, 1);
Blob image2 = user2.getImage();
//输出流输出文件
InputStream inputStream2 = image2.getBinaryStream();
//仅显示文件的大小
System.out.println("图片大小:" + inputStream2.available());
}
17.映射组成关系:即一个没有id的自定义类是另一个自定义类中的属性,那么这个属性可以使用映射组成关系来映射
/**
* 映射组成关系:即一个没有id的自定义类是另一个自定义类中的属性,那么这个属性可以使用映射组成关系来映射
*/
@Test
public void testComponent(){
Worker worker = new Worker();
Pay pay = new Pay();
pay.setMonthlyPay(1000);
pay.setYearPay(12000);
pay.setVocationWithPay(5);
worker.setName("ABC");
worker.setPay(pay);
session.save(worker);
}
以上方法的需要的 实体类 Users.java package com.test.withXml.entity; import java.io.Serializable; import java.sql.Blob; import java.util.Date; public class Users implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String loginName; private String loginPwd; private String name; private String address; private String phone; private String mail; //日期格式 private Date date; //派生的属性 private String Desc; //大文本属性 private String content; //二进制文件 private Blob image; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Blob getImage() { return image; } public void setImage(Blob image) { this.image = image; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPwd() { return loginPwd; } public void setLoginPwd(String loginPwd) { this.loginPwd = loginPwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } public String getDesc() { return Desc; } public void setDesc(String desc) { Desc = desc; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } //1. public Users(String loginName, String loginPwd, String name, String address, String phone, String mail, Date date) { super(); this.loginName = loginName; this.loginPwd = loginPwd; this.name = name; this.address = address; this.phone = phone; this.mail = mail; this.date = date; } //2. public Users() { } @Override public String toString() { return "Users [loginName=" + loginName + ", loginPwd=" + loginPwd + ", name=" + name + ", address=" + address + ", phone=" + phone + ", mail=" + mail + ", date=" + date + "]"; } }Worker.java package com.test.withXml.entity; /** * @author * @version: 1.0 * @Created on: 2018-1-17 下午10:03:14 * 类说明:工人 */ public class Worker { private Integer id; private String name; private Pay pay; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Pay getPay() { return pay; } public void setPay(Pay pay) { this.pay = pay; } }映射文件User.hbm.xml Worker.hbm.xml |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |