Hibernate的数据添加与修改
添加数据:
hibernate提供了这几种添加数据的方法,分别是:
save方法、saveOrUpdate方法、merge方法以及persist方法
在对数据库进行操作时,过程是先开启事务—操作数据库—提交事务
上一篇博客写的hibernate测试类是这样的
//加载配置文件
Configuration configuration = new Configuration().configure();
//获得服务注册对象
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
//定义一个SessionFactory对象
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
//SessionFactory sessionFactory = configuration.buildSessionFactory();
//获得Session
Session session = sessionFactory.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//提交事务
transaction.commit();
//关闭资源
session.close();
sessionFactory.close();
如果每次操作数据都要写这么长一段代码来提交事务是非常不方便的,所以在此基础上建个工具类来优化一下
MySessionFactory.class:
public class MySessionFactory {
private SessionFactory sessionFactory = null;
private Session session = null;
private Transaction transaction = null;
public Session getSession()
{
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
return session;
}
public void commit()
{
transaction.commit();
}
public void close()
{
if(session!=null)
session.close();
if(sessionFactory!=null)
sessionFactory.close();
}
}
写完工具类,再开始写数据库操作语句
save方法:
在save.class类下:
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
// user.setId(1);
user.setAge(1);
user.setName("李白 ");
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
运行后控制台打印sql语句
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
打开数据库,可以看到插入了一条数据,在保存的时候,User对象的id是不用设置的,因为User表的id已经被设置为主键自增长了,即使对id赋值1000,在数据库中插入的id还是为1
在hibernate中有瞬时状态、持久化态、托管状态的概念
瞬时状态的对象可以理解为与数据库无关的对象,例如当定义一个user对象
User user = new User();
user.setAge(1);
user.setName("李 ");
这个user对象就是瞬时状态,无论对user对象的数据如何更改,都不会影响到数据库的数据,这个对象与session会话没有任何关联
但是如果调用save方法保存对象后,user会从瞬时状态转为持久化态,对应数据表中的一条数据,再对user的数据进行更改时,会生成update语句对数据库中的这条数据进行更改
例如save类这样写:
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(1);
user.setName("李白 ");
int key = (int)session.save(user);
user.setName("杜甫");
System.out.println("返回:"+key);
mySessionFactory.commit();
mySessionFactory.close();
}
}
调用save方法保存对象时会返回这个对象的主键,这里把主键打印出来测试一下。上面session调用了save方法并且生成了insert语句,但是这里还没有调用commit进行事务提交,如果在save方法下,对user的name进行更改,改为“杜甫”。再提交时会生成一条update语句来更改修改过的user对象,可以看到控制台输出了两条控制语句
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
返回:6
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
从控制台的sql语句可以看出,在调用save方法时马上生成了insert语句并打印出来,尽管我们对user对象进行了修改,但是依然没有立即打印update语句,而是先打出返回的主键,再打印update语句,说明update语句是在事务提交时才打印的,通过查看数据库,可以看到又插入了一条数据,name为更改过的“杜甫”
persist方法:
和save方法有几点差别,这个方法无返回值,但是与save方法一样,同样将user对象转为持久化态
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(1);
user.setName("李白 ");
session.persist(user);
user.setName("杜甫");
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
由于persist没有返回值,所以只能从user对象中拿到这条数据的id,打印一下,再查看控制台,确实打印除了insert语句,主键id和update语句
另一点不同的地方在于,save无论事务开不开启,只要调用了save方法,首先生成了insert语句。而persist则必须在事务开启的时候才生成insert语句(可以把MySessionFactory工具类中把transaction = session.beginTransaction()这一行注释掉测试一下)
merge方法:
merge方法同样可以用于插入数据,和上面两个不一样的地方在于它还可以修改数据,先看一下如何插入数据
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(1);
user.setName("李白 ");
User user2 = (User) session.merge(user);
user2.setName("范仲淹");
System.out.println("返回:"+user2.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
merge方法是有返回值的,返回这个数据对象,返回的这个数据对象才是与session关联的持久态,如果直接在merge方法后修改user的值是不生效的,因为这个user仅是瞬时态,因此我们需要定义另一个user(即这里的user2)来接收merge返回的对象,这时对user2进行修改操作才能生效,控制台输出sql语句,一条insert语句和一条update语句,测试完成,数据库中又多了一条叫"范仲淹"的数据
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
返回:6
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
再来看一下merge方法的修改操作
如果想要修改数据库中的数据但不想插入新的数据时,可以这样写
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setId(6);
user.setAge(5);
user.setName("李白");
User user2 = (User) session.merge(user);
//user2.setName("范仲淹");
System.out.println("返回:"+user2.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
刚刚已经插入了一条id为6,age为1,name为范仲淹的数据
如果在user对象中将id设置为6,age为5,name为“李白”再调用merge方法时,由于已经存在了id为6的这一条数据,所以hibernate并不会插入新的数据,而是直接将这个id为6的数据查询出来,再使用update语句将查询出来的数据修改为age为5,name为“李白”的数据,下面是控制台打印出来的sql语句
Hibernate:
select
user0_.user_id as user_id1_0_0_,
user0_.age as age2_0_0_,
user0_.name as name3_0_0_
from
tb_user user0_
where
user0_.user_id=?
返回:6
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
当我们对这个返回的对象进行修改时,同样生效。
saveOrUpdate方法:
saveOrUpdate方法是一个保存数据或修改数据的方法,即如果数据表中没有这条数据时则插入数据,又该条数据时则修改数据
例如:
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
//user.setId(6);
user.setAge(5);
user.setName("陆游");
session.saveOrUpdate(user);
//user.setAge(10);
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
这里不设置user对象的id,数据库自动插入了一条新的数据,控制台输出:
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
返回:9
说明保存成功,这里的user转为持久态,在事务提交之前对user对象进行修改依然生成update语句并生效
但是如果我们在插入数据时把id设置为数据表中已有的id时,例如刚刚插入的id为6的数据
如下:
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setId(6);
user.setAge(5);
user.setName("骆宾王");
session.saveOrUpdate(user);
//user.setAge(10);
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
控制台输出update语句,修改成功
返回:6
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
再来看一下数据库,发现刚刚插入的“陆游”已经被修改成“骆宾王”了
修改数据
update方法:
除了上面的saveOrUpdate方法和merge方法可以用来修改数据外,update也可以
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setId(6);
user.setAge(5);
user.setName("刘禹锡");
session.update(user);
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
返回:6
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
此时控制台打印update语句修改了id为6的数据,修改成功
前面的方法能够将瞬时态转变为持久态,但是如果前面的user对象在提交事务前还需要其他用途,不想user对象依然为持久态时,可使用以下方法将被session管理的user对象从持久态中脱离
evict方法:
evict方法需要传入一个Object参数,当你需要某一个对象脱离session管理时,可以将这个对象传给该方法,验证一下,这里插入了两条数据,再将两条数据全部修改为“李白”,在修改之前加入evict方法使user脱离管理
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(5);
user.setName("王安石");
User user2 = new User();
user2.setAge(5);
user2.setName("王维");
session.save(user);
session.save(user2);
session.evict(user);
// session.clear();
user.setName("李白");
user2.setName("李白");
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
返回:5
Hibernate:
update
tb_user
set
age=?,
name=?
where
user_id=?
查看控制台看到打印除了两条insert语句以及一条update语句,这条update语句就是没有被取消托管的user2所做的修改,而user对象已经被取消托管了,再看一下数据表,发现数据表中插入了一条“王安石”(这是被取消托管了,没改为“李白”)和一条“李白”(没被取消托管的那个)
clear方法:
clear方法能够将所有被session托管的持久化态对象全部脱离管理,例如下面代码插入两条数据,并且将两条数据都修改为”李白“,在修改之前,加入clear方法清空session管理的对象
public class save {
public static void main(String[] args) {
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(5);
user.setName("王安石");
User user2 = new User();
user2.setAge(5);
user2.setName("王维");
session.save(user);
session.save(user2);
// session.evict(user);
session.clear();
user.setName("李白");
user2.setName("李白");
System.out.println("返回:"+user.getId());
mySessionFactory.commit();
mySessionFactory.close();
}
}
运行后可以看到控制台只打印了两条insert语句,而没有打印update语句(如果将clear方法去掉,可以看到控制台打印了两条insert语句以及两条update语句)
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
返回:1