1 框架体系结构
2 hibernate入门
1 ORM框架
Object:对象,java对象,此处特指JavaBean
Relational:关系,二维表,数据库中的表。
Mapping :映射|映射元数据,对象中属性,与表的字段,存在对应关系。
ORM 对象和表的映射,就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate是一个数据持久化层的ORM框架,Hibernate提供了对关系型数据库增删改成操作,大大简化了数据访问层繁琐的重复性代码
2 主流的ORM框架
n Hibernate最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
n MyBatis 是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
n 轻量级的dao层组件(不算框架):Apache DBUtils 、Spring JDBCTemplate
3 入门案例【掌握】
1 编写流程
1. 创建数据库和表
2. 导入jar包
3. 创建一个持久化类,编写映射文件 hibernate mapping(*.hbm.xml)
4. 编写核心配置文件(hibernate.cfg.xml)--> 配置获得链接等参数
5 使用api测试
1 数据库和表
create database contacts;
use contact;
create table t_user(
id int auto_increment primary key,
name varchar(50),
pwd varchar(30)
);
2 导入jar包
l需要导入的jar包(一共9个)
Lib-required: 共8个
Mysql-connector-java-5.1.39-bin,jar
3 编写JavaBean + 映射文件
注意:上面两个文件需要在同包下,映射文件为 :类名.hbm.xml
关于*.hbm.xml的书写规范可以直接在hibernate-release-4.1.1.Final文件夹中搜索*.hbm.xml
public class User {
private Integer uid;
private String username;
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
}
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.chinasoft.entity.User" table="t_user">
<!-- 主键 access=field 直接读取字段值,不会调用setter和getter方法-->
<id name="uid" type="java.lang.Integer">
<column name="id" />
<!-- 固定值:主键生成策略,使用数据库本地的方式(mysql自增,oracle序列) -->
<generator class="native" />
</id>
<!-- 普通属性 -->
<property name="username" type="java.lang.String">
<column name="name" />
</property>
<property name="password" type="java.lang.String">
<column name="pwd" />
</property>
</class>
</hibernate-mapping>
注意点:实体类需要满足以下条件
1.提供一个无参数public访问控制符的构造器
2.提供一个标识属性用于映射数据表主键字段
3.所有属性提供public访问控制符的set get方法(javaBean)
4. 标识属性应尽量使用基本数据类型的包装类型(包装类型可以表示null,基本数据类型不可以)
5. 不要用final修饰实体 (将无法生成代理对象进行优化)
4 编写核心配置文件
位置:src目录下
名称:hibernate.cfg.xml
关于hibernate.cfg.xml的书写规范:在hibernate-release.4.1.1.Final中搜索
Ctrl+shift+t : 打开open Type窗口
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- SessionFactory,相当于之前学习连接池配置 -->
<session-factory>
<!-- 基本4项 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///contacts</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!--数据库方言,会针对不同的数据库生成有差异的sql语句 -->
<property name="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect</property>
<!—-是否顯示sql語句 -->
<property name="show_sql">true</property>
<!—格式化sql語句 -->
<property name="format_sql">true</property>
<!-- 添加映射文件:注意是路径不是包名 -->
<mapping resource="com/test/hibernate/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
5 测试
@Test
public void testInsert(){
User user = new User();
user.setUsername("伟哥哥");
user.setPassword("1234");
//1 加载配置文件(hibernate.cfg.xml)获得核心配置对象
Configuration config = new Configuration().configure();
//2 获得工厂 SessionFactory,相当于连接池
//hibernate4.0 之前这样创建
//SessionFactory factory = config.buildSessionFactory();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
SessionFactory factory = config.buildSessionFactory(serviceRegistry);
//3获得会话session,相当于链接Connection
Session session = factory.openSession();
//4 开启事务
Transaction transaction = session.beginTransaction();
//操作
session.save(user);
//5 提交事务 | 回滚事务
transaction.commit();
//6 释放资源--关闭session
session.close();
//7 释放资源--关闭工厂factory
factory.close();
}
4 api详解【多练】
1 体系结构
PO:
PersistentObject
持久化对象
ORM:
O:Object
R: Relational
M:Mapping
对象关系映射
2 Configuration 配置对象
Configuration是hibernate 核心配置文件种类
hibernate.cfg.xml通常使用xml配置文件,可以配置内容更丰富。
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///contacts</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 方言:为不同的数据库,不同的版本,生成sql语句(DQL查询语句)提供依据
* mysql 字符串 varchar
* orcale 字符串 varchar2
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect </property>
<!--是否显示sql语句 -->
<property name="show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 自动创建表(了解),学习中使用,开发不使用的。
* 取值:
update:【】
如果表不存在,将创建表。
如果表已经存在,通过hbm映射文件更新表(添加)。(映射文件必须是数据库对应)
表中的列可以多,不负责删除。
create :如果表存在,先删除,再创建。程序结束时,之前创建的表不删除。【】
create-drop:与create几乎一样。如果factory.close()执行,将在JVM关闭同时,将创建的表删除了。(测试)
validate:校验 hbm映射文件和表的列是否对应,如果对应正常执行,如果不对应抛出异常。(测试)
-->
<property name="hbm2ddl.auto">update</property>
<!-- 添加映射文件 -->
<mapping resource="com/test/hibernate/User.hbm.xml"/>
</session-factory>
User.hbm.xml
<class name="com.test.hibernate.User" table="user">
<id name="uid" column="id">
<generator class="native"/>
</id>
<property name="username" column="name"></property>
<property name="password" column="pwd"></property>
</class>
| Configuration的其他方法: 通过file创建Configuration对象:new Configuration().configure(file) 通过路径创建Configuration对象:new Configuration().configure(path) 通过代码向Configuation中添加mapping resource:new Configuration().addClass(User.class) |
3 SessionFactory工厂
SessionFactory 相当于java web连接池,用于管理所有session
获得sessionFactory方式:
1.hibernate4之前的获取方式:config.buildSessionFactory();
2.hibernate4之后的获取方式:在hibernate4之后,所有的基于hibernate的配置或者服务都应该向ServiceRegistery注册,所以可以通过如下代码获取
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
SessionFactory factory = config.buildSessionFactory(serviceRegistry);
SessionFactory线程安全,可以是成员变量,多个线程同时访问时,不会出现线程并发访问问题。
提供api:
//打开一个新的会话 session
factory.openSession();
//获得当前线程中绑定的会话session,当事务中有多个数据库操作的时候,需要保证操作数据库的session是同一个
factory.getCurrentSession();
注意:要使用factory.getCurrentSession方法,需要在hibernate.cfg.xml添加一条配置
<!-- 与本地线程绑定 -->
<property name=" hibernate.current_session_context_class ">thread</property>
4 Session 的基本使用
l Session 相当于 JDBC的 Connection ,主要用来操作数据库
l Session具有一个缓存,位于缓存中的对应叫做持久化对象
l 使用Session实现数据库的增删改查
save 保存
update 更新
delete 删除
get 通过id查询,立刻发送sql语句
createQuery("hql") 获得Query对象
createCriteria(Class) 获得Criteria对象
注意:在hibernate中删除、更新等操作都是通过主键来操作的,所以要求数据库和实体类必须有主键。
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init() {
// 1 加载配置文件(hibernate.cfg.xml)获得核心配置对象
Configuration config = new Configuration().configure();
// 2创建session工厂
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties())
.buildServiceRegistry();
sessionFactory = config.buildSessionFactory(serviceRegistry);
// 3.获得会话session,相当于链接Connection
session = sessionFactory.openSession();
// 4.开启事务
transaction = session.beginTransaction();
}
@After
public void destory() {
//1. 提交事务 | 回滚事务
transaction.commit();
//2.释放资源--关闭session
session.close();
//3.释放资源--关闭工厂factory
sessionFactory.close();
}
/***
* 保存用户
*/
@Test
public void testInsert(){
User user = new User();
user.setUsername("伟哥哥");
user.setPassword("1234");
//1.操作
session.save(user);
}
/**
* 查询用户
*/
@Test
public void queryUser(){
//参照下面代码
User user = (User)session.get(User.class, 1);
System.out.println(user);
}
//使用hql语言(面向对象)做查询
Query query = session.createQuery("from User");
List<User> list = query.list();
System.out.println(list);
//使用QBC :criteria语言(面向对象)做查询
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
System.out.println(list);
/**
* 修改用户
*/
@Test
public void modifyUser(){
User user = new User();
user.setUid(11);
user.setUsername("haha");;
user.setPassword("1234");
//更新操作
session.update(user);
}
/**
* 删除用户
*/
@Test
public void deleteUser(){
User user = new User();
user.setUid(11);
//删除
session.delete(user);
}
5 Transaction 事务
事务代表一次原子操作,任何持久层的操作都应该在事务下进行,即使是只读操作
开启事务beginTransaction()
获得事务getTransaction()
提交事务:commit()
回滚事务:rollback()
try{
//开启
//session操作
//提交
} catch(e){
//回滚
}
6 工具类
public class H4Utils {
// 会话工厂,整个程序只有一份。
private static SessionFactory factory;
static{
//1 加载配置
Configuration config = new Configuration().configure();
//2 获得工厂
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties())
.buildServiceRegistry();
factory = config.buildSessionFactory(serviceRegistry);
//3 关闭虚拟机时,释放SessionFactory
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("虚拟机关闭!释放资源");
factory.close();
}
}));
}
/**
* 获得一个新的session
* @return
*/
public static Session openSession(){
return factory.openSession();
}
/**
* 获得当前线程中绑定session
* * 注意:必须配置<property name="hibernate.current_session_context_class">thread</property>
* @return
*/
public static Session getCurrentSession(){
return factory.getCurrentSession();
}
}
5 Session一级缓存
1 Session缓存介绍
Session接口的实现中包含一系列的Java集合,这些Java集合构成Session缓存,只要Session实例没有结束生命周期,且没有清理缓存,则存放在session缓存中的对象也不会结束生命周期。
Sesson缓存可以有效的减少Hibernate应用程序访问数据库的频率。
@Test
public void queryUser(){
//查询指定id的用户
User user = (User)session.get(User.class, 1);
User use2 = (User)session.get(User.class, 1);
System.out.println(user);
System.out.println(user2);
}
上面代码仅仅只发送一次sql语句,第二次获取的时候,其实获取的是session缓存中的数据
2 flush方法
flush方法:使数据表中的记录和Session缓存中的状态保持一致,为了保持一致,则可能会发送对应的sql语句。
默认情况下,Transaction的commit方法中会先调用session的flush方法,再提交事务
flush方法会发送一条update语句来更新数据库数据,但不会提交事务(提交事务后数据库数据才会变动)
@Test
public void testSessionFlush(){
//查询指定id的用户
User user = (User)session.get(User.class, 1);
user.setUsername("cccc");
//手动刷新发送update语句(在transaction.commit方法之前加断点,会看到打印)
session.flush();
}
| 注意:这边即使不写session.flush()方法,打印结果仍然有update ……,原因在于transaction的commit操作会自动flush 关联Hibernate源码:关联整个hibernate4.2.4 final就行 快捷键:ctrl+t 查看一个方法的具体实现 |
3 refresh方法
refresh方法会发送一条新的select语句到数据库,更新当前数据信息
@Test
public void testSessionRefresh(){
//查询指定id的用户
User user = (User)session.get(User.class, 1);
System.out.println(user);
//refresh方法会发送一条新的select语句到数据库,更新当前数据信息
//例如在session.refresh方法上加断点,再手动修改数据库数据,此时会看到refresh方法之后打印的user也发生了变化
session.refresh(user);
System.out.println(user);
}
注意:此处需要设施mysql事务的隔离级别
<!—在Hibernate.cfg.xml修改数据库事务的隔离级别
mysql默认事务隔离级别为Repeatable Read,
其他数据库一般为Read Commited-->
<property name="hibernate.connection.isolation">2</property>
4 事务隔离级别
未授权读取 默认值:1
也称为读未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。
出现的问题:出现了脏数据
解决问题思路:禁止读取未提交的数据
授权读取 默认值:2
也称为读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
出现的问题:我在读取数据的时候别人修改了同一条数据,造成两次访问结果不一致
解决问题的思路:我在读取指定数据的时候别人不可以修改该指定数据
可重复读取 默认值:4
可重复读取(Repeatable Read):禁止不可重复读取(连续两次读取,读取的数据是一致的,同样会造成查询数据错误)和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
出现的问题:我和老婆并没有同时操作同一条数据,但是因为我新增了数据造成了别人读取的步正确。
解决问题的思路:让事务不能并发执行
序列化 默认值:8
序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
5 clear方法
clear清理缓存:
@Test
public void testSessionClear(){
//查询指定id的用户
User user = (User)session.get(User.class, 1);
System.out.println(user);
//清空缓存
session.clear();
User user2 = (User)session.get(User.class, 1);
System.out.println(user2);
}
//这边会打印两个select …from 原因是session清空了
6 .Hibernate中持久化对象与session详解
hibernate持久化状态分类:临时状态、持久化状态、托管状态
临时状态:
由Java的new命令开辟内存空间的java对象也就是普通的java对象,如果没有变量引用它它将会被JVM收回。临时对象在内存中是孤立存在的,它的意义是携带信息载体,不和数据库中的数据由任何的关联。
通过Session的save()方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映射插入数据库中,这个临时对象就成为持久化对象。
持久化状态:
持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的session声明周期中保存这个状态。如果是直接数据库查询所返回的数据对象,则这些对象和数据库中的字段相关联,具有相同的id,它们马上变成持久化对象。如果一个临时对象被持久化对象引用,也立马变为持久化对象。
如果使用delete()方法,持久化对象变为临时对象,并且删除数据库中相应的记录,这个对象不再与数据库有任何的联系。
持久化对象总是与Session和Transaction关联在一起,在一个session中,对持久化对象的操作不会立即写到数据库,只有当Transaction(事务)结束时,才真正的对数据库更新,从而完成持久化对象和数据库的同步。
当一个session()执行close()、clear()、或evict()之后,持久化对象就变为离线对象,这时对象的id虽然拥有数据库的识别值,但已经不在Hibernate持久层的管理下,他和临时对象基本上一样的,只不过比临时对象多了数据库标识id。没有任何变量引用时,jvm将其回收。
Hibernate使用OID来建立内存中的对应和数据库中记录的对应关系。对象的OID和数据库表的主键对应。为保证OID的唯一性,应该让hibernate来为OID赋值
脱管状态:
Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,可以继续对这个对象进行修改,如果脱管对象被重新关联到某个新的Session上,会在此转成持久对象。
脱管对象虽然拥有用户的标识id,所以通过update()、saveOrUpdate()等方法,再次与持久层关联。
1 Save方法
/**
* save方法使一个临时对象变为持久化对象
* save方法为对象分配一个id
* 在save方法之前设置的id无效
* 持久化对象的id是不允许被修改的
*/
@Test
public void testSave(){
User user = new User();
user.setUsername("伟哥哥");
user.setPassword("1234");
System.out.println(user);
//1.操作
session.save(user);
System.out.println(user);
}
<!-- dynamic-insert:优化插入的sql语句-->
<class name="User" table="t_user" dynamic-insert="true">
2 Get和load方法
get 通过id查询,立刻发送sql语句。如果没有 null
load 通过id查询,调动方法没有发送sql语句,使用对象的时候才查询数据库。如果没有抛异常
@Test
public void queryUser(){
//查询指定id的用户
User user = (User)session.get(User.class, 1);
System.out.println(user);
}
| |
public void queryUser(){
//查询指定id的用户
User user = (User)session.load(User.class, 1);
session.close();
System.out.println(user);
}
//上面代码会抛懒加载异常,因为session已经关了,而load方法再使用到user的时候会去查询数据库,没有session而去查数据库,报异常
3 update方法
/**
* 1.更新一个持久化对象,无需显示调用session.update()方法,因为transaction.commit()方法会自动调用session的flush方法
* 2.更新一个游离对象,需要显示调用session.update()方法,此时才会更新数据库,此时会把一个游离对象转换为持久化对象
*/
@Test
public void testUpdate(){
//持久化对象
User user = (User)session.get(User.class, 1);
System.out.println(user);
user.setUsername("aaa");
//此处无需调用session.update(user)方法,在调用transaction.commit()方法的时候会自动发送update更新语句
transaction.commit();
//关闭session会清空缓存,此时user变为游离对象
session.close();
//新开一个session,和原来的session已经没关系了
session = sessionFactory.openSession();
//新开事务
transaction = session.beginTransaction();
//重新设置user的名字,如果此时不调用session.update(user),则默认的transaction.commit()方法不会自动发送update语句,原因是此时user为游离对象了
user.setUsername("bbbb");
session.update(user);
}
4 saveOrUpdate方法
同时包含了save()与update()方法的功能
@Test
public void testSaveOrUpdate(){
User user = new User();
user.setUsername("小小");
user.setPassword("1234");
//如果没有id,则执行save方法
//如果有id,但数据库没有和数据相关的记录,则会抛出异常
//如果有id,但数据库有和数据相关的记录,则执行update
//user.setUid(100);
session.saveOrUpdate(user);
}
5 delete方法
|
6 evict方法
从缓存中把指定的持久化对象移除
@Test
public void testEvict(){
User user1 = (User)session.get(User.class, 1);
User user2 = (User)session.get(User.class, 12);
user1.setUsername("AAA");
user2.setUsername("BBB");
//将user2从缓存中移除(user2不会更新数据库)
session.evict(user2);
}
<!--update="false" :不允许更新该字段值 -->
<property name="username" type="java.lang.String" update="false">
<column name="name" unique="true" length="20"/>
</property>
7 配置c3p0数据源
1 导入libàoptionalàc3p0下的jar包
2 在hibernate.cfg.xml添加如下配置
| hibernate.c3p0.max_size: 数据库连接池的最大连接数 hibernate.c3p0.min_size: 数据库连接池的最小连接数 hibernate.c3p0.timeout: 数据库连接池中连接对象在多长时间没有使用过后,就应该被销毁 hibernate.c3p0.max_statements: 缓存 Statement 对象的数量 hibernate.c3p0.idle_test_period: 表示连接池检测线程多长时间检测一次池内的所有链接对象是否超时. 连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次被使用时间和当前时间的时间差来和 timeout 做对比,进而决定是否销毁这个连接对象。 hibernate.c3p0.acquire_increment: 当数据库连接池中的连接耗尽时, 同一时刻获取多少个数据库连接
//jdbc操作数据库的时候statement读取数据每次从数据库读取的数据条数 hibernate.jdbc.fetch_size:实质是调用 Statement.setFetchSize() 方法设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数。 ² 例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会 1 次性把1万条取出来的,而只会取出 fetchSize 条数,当结果集遍历完了这些记录以后,再去数据库取 fetchSize 条数据。因此大大节省了无谓的内存消耗。Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。Oracle数据库的JDBC驱动默认的Fetch Size = 10,是一个保守的设定,根据测试,当Fetch Size=50时,性能会提升1倍之多,当fetchSize=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持 //jdbc操作数据库的时候statement删除数据每次从数据库删除的数据条数 hibernate.jdbc.batch_size:设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,类似于设置缓冲区大小的意思。batchSize 越大,批量操作时向数据库发送sql的次数越少,速度就越快。 ² 测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!Oracle数据库batchSize=30 的时候比较合适。 |
<!--配置c3p0 -->
<!--c3p0最大连接数 -->
<property name="hibernate.c3p0.max_size">10</property>
<!--c3p0最小连接数 -->
<property name="hibernate.c3p0.min_size">5</property>
<!--c3p0中连接对象多久后没有被使用应该被销毁-->
<property name="hibernate.c3p0.timeout">2000</property>
<!--c3p0连接池检测线程多久检测一次池内所有链接对象是否超时-->
<property name="hibernate.c3p0.idle_test_period">2000</property>
<!--c3p0缓存statement数量-->
<property name="hibernate.c3p0.max_statements">10</property>
<!--c3p0连接池中连接耗尽时一次获取的连接数-->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!--对数据库进行批量查询时,配置一次查询获取数据的条数-->
<property name="hibernate.jdbc.fetch_size">100</property>
<!--对数据库进行批量删除时,配置一次删除删除数据的条数-->
<property name="hibernate.jdbc.batch_size">30</property>
//测试当前session中的connection是否来自c3p0
@Test
public void testDowork(){
session.doWork(new Work() {
@Override
public void execute(Connection connection)throws SQLException {
// TODO Auto-generated method stub
System.out.println(connection);
}
});
}
3 更多配置项
本文介绍了Hibernate框架的基础概念,包括其作为ORM框架的作用原理及如何通过对象-关系映射简化数据库操作。此外,还详细讲解了Hibernate的入门案例,涵盖数据库配置、核心配置文件编写、映射文件设置等内容。
1万+

被折叠的 条评论
为什么被折叠?



