hibernate如果有非常多的对象转换成sql就不如MyBatis自己写sql来的快了,因为它有一个转换的过程。
Navicat Premium 11 64位本来也放在上面百度云盘中
create database hibernate_day1;
use hibernate_day1;
create table t_user(
id int auto_increment primary key,
username varchar(50),
password varchar(30)
);
这里我们使用3.6.10的版本开发,4.0开发是建议使用注解
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day1property>
<property name="hibernate.connection.username">rootproperty>
<property name="hibernate.connection.password">rootproperty>
<property name="show_sql">trueproperty>
<property name="format_sql">trueproperty>
<property name="hibernate.connection.autocommit">trueproperty>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialectproperty>
<mapping resource="com/it/hibernate/domain/User.hbm.xml" />
session-factory>
hibernate-configuration>
<hibernate-mapping>
<class name="com.it.hibernate.domain.User" table="t_user">
<id name="uid" column="id">
<generator class="native">generator>
id>
<property name="username">property>
<property name="password">property>
class>
hibernate-mapping>
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class Demo1 {
@Test
public void test1(){
//1.获取核心配置文件对象,默认是加载src的hibernate.cfg.xm文件
//new Configuration()加载的是hibernate.properties,.configure()才是加载src的hibernate.cfg.xm
Configuration cfg = new Configuration().configure();
//2.创建会话工厂
SessionFactory factory = cfg.buildSessionFactory();
//3.创建会话
Session sessoin = factory.openSession();
//4.开启事务
Transaction trans = sessoin.getTransaction();
trans.begin();
//5.保存
User user = new User();
user.setUsername("shu01");
user.setPassword("123");
sessoin.save(user);
//6.提交事务
trans.commit();
//7.关闭会话
sessoin.close();
//8.关闭工厂,释放资源
factory.close();
}
}
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day1?serverTimezone=UTCproperty>
也可以通过修改my.cnf配置文件修改时区
default-time_zone = ‘+8:00’
重启mysql使新时区生效
<mapping resource="com/it/hibernate/domain/User.hbm.xml" />
使用cfg.addResource(“com/it/hibernate/domain/User.hbm.xml”);
或者使用cfg.addClass(User.class);,都要注释hibernate.cfg.xml里的maping,否则冲突
平时开发中:将 实体.hbm.xml 映射,配置在hibernate.cfg.xml中,即mapping配置
<property name="hibernate.current_session_context_class">threadproperty>
package com.it.hibernate.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class Demo2 {
@Test
public void test1(){
//保存用户数据
//1.获取核心配置文件对象,默认是加载src的hibernate.cfg.xm文件
Configuration cfg = new Configuration().configure();
//2.创建会话工厂
SessionFactory factory = cfg.buildSessionFactory();
/* sessionFactory提供了两个方法来获取session
1.factory.openSession() 获取一个全新的session
2.factory.getCurrentSession() 获取一个与当前线程绑定的session*/
//都是新的session,hashCode不同
Session session1 = factory.openSession();
Session session2 = factory.openSession();
System.out.println(session1.hashCode());
System.out.println(session2.hashCode());
//共享的,相同session
Session session3 = factory.getCurrentSession();
Session session4 = factory.getCurrentSession();
System.out.println(session3.hashCode());
System.out.println(session4.hashCode());
//3、4与5、6不同线程session不同
new Thread(){
public void run() {
//同一个线程共享,相同的session
Session session5 = factory.getCurrentSession();
Session session6 = factory.getCurrentSession();
System.out.println(session5.hashCode());
System.out.println(session6.hashCode());
};
}.start();
//4.关闭会话
//如果是通过open方法打开session,要自己关闭
session1.close();
session2.close();
//如果是通过get方法获取session,session不需要关闭,因为事务提交或者回滚会自动关闭
//5.关闭工厂,释放资源
factory.close();
}
}
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class Demo3 {
@Test
public void test1(){
//保存用户数据
//1.获取核心 配置文件对象
Configuration cfg = new Configuration().configure();
//2.创建会话工厂
SessionFactory factory = cfg.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = factory.openSession();
//4.事务
//4.1获取事务
Transaction trans = session.getTransaction();
//4.2开启事务【没有开启事务和提交事务,数据是不会存入数据库中的】
trans.begin();//也可以用Session.beginTransaction();
//插入数据
User user = new User("shu03","123");
session.save(user);
//4.3回滚事务
//trans.rollback();//回滚事务,这个代码写在catch中
//4.4提交事务
trans.commit();
//5.关闭会话
session.close();
//6.关闭工厂,释放资源
factory.close();
}
}
try{
//开启
//session操作
//提交
} catch(e){
//回滚
}
注释事务,sql能运行,数据库中也成功插入数据,这是因为我们一开始在hibernate.cfg.xml文件中配置置了自动提交事务
再将它注释,发现sql能运行,数据库中无数据插入,因为没有开启事务和提交事务,数据是不会存入数据库中的
<property name="hibernate.connection.autocommit">trueproperty>
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.junit.Test;
public class Demo4 {
@Test
public void test1(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
//save保存,插入数据,需要提交事务
User user1 = new User("shu04","123");
session.save(user1);
//get查询,根据id查询,hibernate会根据类名查表,如果没找到,返回null值
User user2 = (User) session.get(User.class, 19);//强转为User
System.out.println(user2);//User要提供toString方法
//load查询,根据id查询,如果没查到,会抛出ObjectNotFoundException异常
User user3 = (User) session.load(User.class, 19);
System.out.println(user3);//User要提供toString方法
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.junit.Test;
public class Demo5 {
@Test
public void test1(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
/* delete删除数据的两种方式
1.先get方法获取删除对象,再使用delete方法删除
2.它内部删除是根据id来删除,先获取比较麻烦,还要查询一次
直接创建一个User对象,设置id,再调用delete方法
*/
/*由于在hibernate.cfg.xml中配置的自动提交事务
对insert有效,对delete无效,所有要我们自己开启、提交事务
*/
//开启事务
session.getTransaction().begin();
//删除方法1
User user1 = (User) session.get(User.class, 20);
session.delete(user1);
//删除方法2
User user2 = new User();
user2.setUid(23);
session.delete(user2);
//提交事务
session.getTransaction().commit();
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
如果数据库中没有对应的id,会报错
1.org.hibernate.StaleStateException: Batch update returned unexpected row count from update [1]; actual row count: 0; expected: 1
2.java.lang.IllegalArgumentException: attempt to create delete event with null entity
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.junit.Test;
public class Demo6 {
@Test
public void test1(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
/* update更新数据
方式1:先使用get方法获取对象,再使用set方法设置值,事务提交,自动执行update
方式2:自己封装User,设置id,这个时候,需要调用update方法
*/
//开启事务
session.getTransaction().begin();
//update方法1,从数据库获取信息,修改
User user = (User) session.get(User.class, 24);
user.setPassword("456");
//1.1更新使用update方法【一般使用这个】
//update方法判断user,有id会更新,没有id,会报错!
session.update(user);
//1.2更新也可以调用save方法
//save方法判断user,有id会更新
//session.save(user);
//1.3更新还可以使用saveOrUpdate方法:
//saveOrUpdate方法会判断user里有没有id,有id,更新数据,没有id,插入数据
//saveOrUpdate(user);
//1.4更新还可以什么都不写,注释上面的session.update(user);,
//发现也能执行成功,这是由于模型的状态(托管、游离)
//update方法2,自己封装User,设置id,这时必须要调用update方法,不能不写,否则更新不了
User user1 = new User();
user1.setUid(25);
user1.setUsername("shu06");
user1.setPassword("123456");
session.update(user1);//这时必须要写update方法
//提交事务
session.getTransaction().commit();
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
注意:这里update方法1中只设置了password,但是执行的时候却设置了username,这是update的特性,会根据id把里面的值重新设置一遍,性能浪费,不如只更新我们所需要更新的那个字段性能好。
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.junit.Test;
import java.util.List;
public class Demo8 {
@Test
public void test1(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
//HQL:Hibernate Query Language
//(1).查询所有用户【注意:User类名】
Query query = session.createQuery("from User ");//from大小写都可以
//(2).查询带条件的用户【注意:username和password是User的对象属性,而不是表的字段名】
Query query1 = session.createQuery("from User where username = ? and password = ? ");
query1.setParameter(0,"shu04");//0代表第一个?
query1.setParameter(1,"456");//1代表第二个?
//(3).分页(limit ?,?)
//Query query = session.createQuery("from User ");
query.setFirstResult(0);//相当于limit 0,3 第一页,每页显示条数3
query.setMaxResults(3);//3,3 第二页,每页显示条数3
//第一页开始0、第二页开始3,计算方法:(页数-1)*每页显示条数
//(4).查询返回单行数据
//它只返回唯一一个,否则报错
/*User user = (User) query.uniqueResult();
System.out.println(user);*/
//(5).执行查询,返回多行数据
List<User> list = query.list();
//遍历
for (User user : list) {
System.out.println(user);
}
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
一些概念:
PO:persistent object ,用于与数据库交互数据。–dao层 (JavaBean + hbm )
BO:Business object 业务数据对象。–service层
VO:Value Object 值对象。–web层
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
public class Demo9 {
@Test
public void test9(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
//Criteria:Hibernate独创的查询对象,全程无hql语句
Criteria criteria = session.createCriteria(User.class);
//【eq = 】(等于)
//查询数据库中username为shu04、password为456的数据
//criteria.add(Restrictions.eq("username", "shu04"));
//criteria.add(Restrictions.eq("password", "456"));
//System.out.println(criteria.uniqueResult());
//【gt >】 【ge >=】
//查询数据库中id大于等于27的数据
//criteria.add(Restrictions.ge("uid",27));
//System.out.println(criteria.list());
//【lt <】 【le <=】 可以按住Ctrl点击Restrictions查看更多
//【模糊查询 like】
criteria.add(Restrictions.like("username","s%"));
System.out.println(criteria.list());
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
package com.it.hibernate.test;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.junit.Test;
import java.util.List;
public class Demo10 {
@Test
public void test9(){
//保存用户数据
//1.获取核心配置文件对象
Configuration configure = new Configuration().configure();
//2.创建会话工厂
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.通过会话工厂获取session对象
Session session = sessionFactory.openSession();
//使用原生的sql来查询语句
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
//直接遍历发现,查询结果的每一行数据存储在一个数组中,数组又存在集合中
//所以要再遍历
List<Object[]> list = sqlQuery.list();
for (Object[] obj : list) {
for (Object o : obj) {
System.out.println(o);
}
System.out.println("-----------");
}
//4.关闭会话
session.close();
//5.关闭工厂,释放资源
sessionFactory.close();
}
}
吐槽:虽然hibernate留了后门给我们使用,可以使用原生sql,但是这里我们还不如使用DBUtils,只用导入一个jar包。。。
package com.it.hibernate.uitls;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory factory;
static{
//1.获取核心配置文件对象
Configuration configuration = new Configuration().configure();
//2.创建会话工厂
factory = configuration.buildSessionFactory();
//监听程序关闭,关闭时释放会话工厂
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
//System.out.println("Program shutdown...");//程序关闭
//关闭会话工厂
factory.close();
}
});
}
public static Session openSession(){
return factory.openSession();
}
public static Session getCurrentSession(){
return factory.getCurrentSession();
}
}
package com.it.hibernate.test;
import com.it.hibernate.uitls.HibernateUtils;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.junit.Test;
import java.util.List;
public class Demo10 {
@Test
public void test9(){
//使用HibernateUtils获取session对象
Session session = HibernateUtils.openSession();
//使用原生的sql来查询语句
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
//直接遍历发现,查询结果的每一行数据存储在一个数组中,数组又存在集合中
//所以要再遍历
List<Object[]> list = sqlQuery.list();
for (Object[] obj : list) {
for (Object o : obj) {
System.out.println(o);
}
System.out.println("-----------");
}
//关闭会话
session.close();
}
}