事务
事务的特性
原子性:指事务是一个不可分割的工作单位。
事务中的操作要么都发生,要么都不发生
一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务
不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的
接下来即使数据库发生故障也不应该对其有任何影响
使用事务
用事务的sql语句(事务开始和事务提交)包裹住要执行的语句
1.把事务打开
2.写要执行sql语句
3.把事务进行提交
4.当遇到突发事件(如遇到断电)事务没有提交,那么事务会自动回滚
例如:
begin;
update 表 set money=money-100 where username='a';
update 表 set money=money+100 where username='b';
commit;
事务的隔离级别
赃读:指一个事务读取了另一个事务未提交的数据。
(比如:转账还钱,没提交就回滚了)
不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。
一个事务读取到了另一个事务提交后的数据。(update)
(比如:我从柜台取钱,我母亲从ATM取钱 柜台小姐 发现账户数据在跳动)
虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(insert)
mysql默认隔离级别:REPEATABLE READ:避免赃读、不可重复读。虚读有可能发生。
hibernate
操作数据的对象关系型数据库
使用面向对象的思想去增删改查,避免使用繁琐的sql语句去操作数据
添加对象到数据库
@Test
public void fun1() {
// 1.加载配置文件
// 直接调用configure() 系统会默认读取 hibernate.cfg.xml这个文件
Configuration configuration = new Configuration().configure();
// 2.获取sessionFactory对象 相当于获取连接池对象
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.从工厂中获取一个session对象
// openSession 获取的是一个全新的session
Session session = sessionFactory.openSession();
// 向数据库插入对象
User user = new User();
user.setUsername("SC");
user.setPassword("123");
// 4.使用session对象开启一个事务 返回一个事务对象transaction
Transaction transaction = session.beginTransaction();
// 包裹的要执行的任务
session.save(user);
// 5.提交事务
transaction.commit();
// 6.关闭资源
session.close();
sessionFactory.close();
}
修改对象
@Test
public void fun2() {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 修改对象
// 1.获取对象(根据id获取)
User user = session.get(User.class, 1);
// 2.修改对象
user.setUsername("zb");
user.setPassword("1");
// 3.把对象更新一遍 注意:修改的时候就使用update
//session.save(user);
session.update(user);
transaction.commit();
session.close();
sessionFactory.close();
}
查询
方式一:
@Test
public void fun3() {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 查询
User user = session.get(User.class, 1);
System.out.println(user);
transaction.commit();
session.close();
sessionFactory.close();
}
方式二:
@Test
public void fun4() {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 查询
User user = session.load(User.class, 1);
System.out.println(user);
transaction.commit();
session.close();
sessionFactory.close();
// 报错原因:这时代理对象 才会使用session去查询数据库
// 而session已经销毁了
// System.out.println(user);
}
get和load方法的区别
相同:都能进行对象的查询
不同:
load方式的查询方式是懒加载(延迟加载)
当load方法被执行的时,不会跟get方法一样立即生成sql语句执行
而是生成一个代理对象直接返回
只有当你访问了代理对象的属性时
这时才会去生成sql语句 查询数据库
利用延迟加载提高了hibernate的执行效率
删除
@Test
public void fun5() {
Configuration configuration = new Configuration().configure();
// sessionFactory线程安全的
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 删除
// 1.先查对象 把该对象删除
// User user = session.get(User.class, 1);
// session.delete(user);
// 2.创建一个对象 只赋值id 删除
User user = new User();
user.setId(2);
session.delete(user);
transaction.commit();
session.close();
sessionFactory.close();
}
简单封装
public class HibernateUtils {
// 把sessionFactory写成成员变量
private static SessionFactory sessionFactory;
static {
// 加载配置文件
Configuration configuration = new Configuration().configure();
// 创建session工厂
sessionFactory = configuration.buildSessionFactory();
}
// 返回session的方法
public static Session getSession() {
return sessionFactory.openSession();
}
// 返回当前session的方法
public static Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
使用HQL查询
@Test
public void fun6() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 返回的是保存查询结果的对象
//Query<User> query = session.createQuery("from com.lanou3g.User");
Query<User> query = session.createQuery("from User", User.class);
// 获取到查询结果的集合
List<User> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
SQL语句查询
@Test
public void fun7() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 直接使用sql语句查询
NativeQuery<Object[]> nativeQuery = session.createNativeQuery("select * from user");
List<Object[]> list = nativeQuery.list();
// list中保存三个对象 每一个对象是一个Object[]
// 遍历
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
transaction.commit();
session.close();
}
hibernate配置文件
配置文件的默认名字 hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根标签 -->
<hibernate-configuration>
<!-- session-factory 相当于数据库连接池 -->
<session-factory>
<!-- 加载了数据库的驱动类 基础设置 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
<!-- hibernate方言 配置使用哪个类 全限定类名 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 在控制台输出sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 美化sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- hbm2ddl.auto 是否自动生成表结构 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 注意:映射实体类 全文件名 从包名开始 -->
<!-- 关联实体类对应的描述文件 -->
<mapping resource="com/lanou3g/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
实体类
需要创建实体类 配置对应的映射文件
名字规范:
1.与实体类名字相同
2.与实体类在同一个包下
3.xml文件
User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 让实体类与数据库中的表建立起关系(字段与属性建立关系) -->
<!-- package 可以添加包名 添加后 底下可以省略包名 -->
<hibernate-mapping package="com.lanou3g">
<!-- 全类名 -->
<class name="User" table="user">
<!-- 设置主键关联 注意:表中必须要有主键 -->
<id name="id" column="id">
<!-- 主键生成策略 -->
<generator class="native"></generator>
</id>
<!-- 配置非主键属性 -->
<property name="username" column="username"></property>
<property name="password" column="password"></property>
<!-- 注意:配置完映射文件后 需要跟配置文件进行关联 -->
</class>
</hibernate-mapping>