就像奶茶大续杯一样,让我们继续和Hibernate打交道,捧好温热的奶茶在这个寒冬里,继续Hibernate的学习。
1、我们的配置hibernate.cfg.xml文件的主要作用就是创建一个sessionFactory,其会通过property配置一些数据库的连接,
也会配置Hibernate的相关属性比如方言、自动创建表机制、格式化sql等,还有就是持久化类的所在路径。
当只是用Hibernate的时候主要是用Hibernate从配置文件里获取sessionFactory,再从sessionFactory中取session,再用session对持久化对象进行操作。
2、hibernate默认加载就是名为hibernate.cfg.xml的配置文件,这是在源代码里面的
public Configuration configure() throws HibernateException {
//1.StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME的值是"hibernate.cfg.xml"
return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME );
}
3、配置SeesionFactory的方式有两种,一种是通过DataSource来配置sessionFactory,另一种是通过Hibernate.cxg.xml来配置。通过DataSource的方法,是Datasource数据源是注入给sessionfactory的SessionFactory是基于dataSource上建立的。
4、在单独使用hibernate的方法时,我们应该这样做
com.test.entity
update
org.hibernate.dialect.MySQL57Dialect
org.springframework.orm.hibernate5.SpringSessionContext
false
true
b、配置jdbc.properties
jdbc.master=master
master.key=21231312
master.driverClass=com.mysql.jdbc.Driver
#master.jdbcUrl=120.0.0.1
#root 填你自己的账号,密码,这里的属性配置只是换了一种形式,之后会通过spring读取到
master.user=test
master.password=test
master.filters=stat
master.initialPoolSize=5
master.minPoolSize=5
master.maxPoolSize=15
master.maxWait=20000
master.timeBetweenEvictionRunsMillis=60000
master.minEvictableIdleTimeMillis=300000
master.validationQuery=SELECT 1
master.testWhileIdle=true
master.testOnBorrow=false
master.testOnReturn=false
master.poolPreparedStatements=false
master.maxPoolPreparedStatementPerConnectionSize=200
c、根据自己的实际情况来,在生成的实体类上打上注解,@Column这个注解有些属性
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
//被标注字段在数据库表中所对应字段的名称
String name() default "";
//表示该字段是否为唯一标识,默认为false。同@Table标记中的@UniqueConstraint
boolean unique() default false;
//该字段是否可以为null值,默认为true
boolean nullable() default true;
//在使用“INSERT”脚本插入数据时,是否需要插入该字段的值,一般多用于只读的属性
boolean insertable() default true;
//在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值,一般多用于只读的属性
boolean updatable() default true;
//创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用,但DB中表已经建好就可不用
String columnDefinition() default "";
//定义了包含当前字段的表名
String table() default "";
//字段的长度,当字段的类型为varchar时,该属性才有效
int length() default 255;
//表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数。
int precision() default 0;
int scale() default 0;
}
d、为你操作的持久类设置值,这个操作一般都在Service层中
XXXPO xxxPO = new XXXPO();
xxxPO.setCompanyId(companyId);
xxxPO.setType(type);
xxxPO.setCreateTime(DateTimeHelper.long2TimeStamp(System.currentTimeMillis()));
XXXDao.insertRedPoint(redPoint);
e、在DAO层使用@Repository 和@Resource注解和对应的语句进行持久化操作,以下列举了多种的Hibernate查询的方法
/*当Service需要使用Spring创建的名字叫“XXXXDao”的XXXXDaoImpl实例时,
就可以使用@Resource(name = "userDao")注解告诉Spring,
Spring把创建好的userDao注入给Service即可。
注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能
*/
@Repository
public class XXXXDaoImpl extends AbstractDao implementsXXXXDao {
private static final Logger logger = LoggerFactory.getLogger(XXXXDaoImpl.class);
@Resource 用来装配bean
private SessionFactory sessionFactory;
private Session getSession() {
return sessionFactory.getCurrentSession();
}
private Connection conn;
public XXXXDaoImpl() {
}
public XXXXDaoImpl(Connection con) {
this.conn = con;
}
@Override
public void updateCheckCount(Integer announcementId) throws SQLException {
/**
* 对象查询(Query By Criteria)
* 1、CriteriaBuilder可以用于创建CriteriaQuery、CriteriaUpdate和CriteriaDelete。
* 除此之外类似count、max等函数也是由CriteriaBuilder来创建的
* 2、调用criteriaBuilder.createQuery来创建CriteriaQuery。
* 其中createQuery的参数是Query返回值类型
* 3、调用query.from(Order.class),参数是对应于数据库里表的实体类,
* query.from类似于sql中的from语句,该方法的执行等价于sql中的from order。
* 4、调用 query.select创建映射,query.select(criteriaBuilder.count(root.get(“id”)))等价于select count(id)。
* 如果执行query.select(root)则等价于select *。
* 5、使用CriteriaBuilder构造查询条件Predicate,该predicate也就是在where后面的条件子句。
* 6、getSession().createQuery(criteriaQuery).uniqueResultOptional()最后执行查询获取数据
*/
CriteriaBuilder builder = getSession().getCriteriaBuilder();
CriteriaQuery criteriaQuery = builder.createQueryXXXXPO.class);
Root root = criteriaQuery.from(AnnouncementPO.class);
criteriaQuery.select(root);
criteriaQuery.where(builder.equal(root.get("id"), announcementId));
Optional xxxxPO = getSession().createQuery(criteriaQuery).uniqueResultOptional();
//如果Optional实例有值则将其返回,否则返回orElse方法传入的参数
XxxxPO xxxx = announcementPO.orElse(null);
getSession().save(announcement);
}
/**
1、主键查询的方法有两种方法:get()和load()支持懒加载
*/
User u = (User) session.get(User.class, 1);
User u = (User) session.load(User.class, 1);
/**
* 2、HRL查询,查询全部信息,支持方法链的编程,即直接调用list()方法
* 注意HRL查询的是实体类的名称,不是数据表的名称,特别注意这一点
*/
//2.1查询所有 会得到list集合 Query q=session.createQuery("from User");
//2.2 条件查询 (包括正序asc倒序desc)如下
Query query = session.createQuery("from Good where gname = ? and gmono =?");
query.setParameter(0, "面包");
query.setParameter(1, "奶油面包");
List list = query.list();
//2.3 分页查询
Query query = session.createQuery("from Good");
//2.3.1设置第一个要查询的位置(计算公式:(当前页数-1)*每页的记录数)
query.setFirstResult(0);
//2.3.2设置每页显示的最大记录数
query.setMaxResults(3);
// 2.3.3使用Query对象的list方法得到数据集合
List list = query.list();
//2.4聚集函数查询
Query query = session.createQuery("select count(*) from Good");
Object obj = query.uniqueResult();//获取结果(结果为long类型)
Long long1 = (Long) obj;//转化为long(类型为long,转为int会报错)
int count = long1.intValue();
/**
*2.5多表查询和sql语法一样
* 内连接查询
* 显示内连接
* select * from customers c inner join orders o on c.cid = o.cno;
* 隐式内连接
* select * from customers c,orders o where c.cid = o.cno;
* 外连接查询
* 左外连接
* select * from customers c left join orders o on c.cid = o.cno;
* 右外连接
* select * from customers c right join orders o on c.cid = o.cno;
*/
/**
3、完全的面向对象的查询
*/
//3.1. 简单查询,使用的是Criteria接口
List list = session.createCriteria(Customer.class).list();
//3.2 排序查询
Criteria criteria = session.createCriteria(Linkman.class);
criteria.addOrder(Order.desc("id"));
List list = criteria.list();
//3.3分页查询
Criteria criteria = session.createCriteria(Linkman.class);
criteria.addOrder(Order.desc("lkm_id"));
criteria.setFirstResult(0);
criteria.setMaxResults(3);
List list = criteria.list();
/**3.4条件查询
* 条件查询使用Criteria接口的add方法,用来传入条件。
* 使用Restrictions的添加条件的方法,来添加条件,例如:
* Restrictions.eq -- 相等
* Restrictions.gt -- 大于号
* Restrictions.ge -- 大于等于
* Restrictions.lt -- 小于
* Restrictions.le -- 小于等于
* Restrictions.between -- 在之间
* Restrictions.like -- 模糊查询
* Restrictions.in -- 范围
* Restrictions.and -- 并且
* Restrictions.or -- 或者
*/
Criteria criteria = session.createCriteria(User.class);
//a、添加条件
criteria.add(Restrictions.eq("id", 1));
//查询全部,没有sql语句
List list = criteria.list();
//b、多条件
Criteria criteria = session.createCriteria(Linkman.class);
// 设置排序
criteria.addOrder(Order.desc("lkm_id"));
// 设置查询条件
criteria.add(Restrictions.or(Restrictions.eq("lkm_gender", "男"), Restrictions.gt("lkm_id", 3L)));
List list = criteria.list();
/**
* 3.5 聚合条件查询 criteria.setProjection()
*/
Criteria criteria = session.createCriteria(Linkman.class);
criteria.setProjection(Projections.rowCount());
List list = criteria.list();
Long count = list.get(0).longValue();
System.out.println(count);
/**
* 4、本地查询sql语句,适合使用复杂的查询,
或者不想使用HQL或者criteria查询,可以使用本地sql查询
*/
//sql语句
SQLQuery sql = session.createSQLQuery("select * from user ");
SQLQuery sql = session.createSQLQuery("select * from user where id=1 ");
sql.addEntity(User.class);
List list = sql.list();
System.out.println(list);
String sql = "UPDATE USER SET NAME = ? WHERE id =1";
getSession().createSQLQuery(sql).setParameter(1, id).executeUpdate();
小猴,在这边提醒如果只是使用hibernate的话,又想要spring托管,就要在初始化的时候让其起到作用
new ClassPathXmlApplicationContext("applicationContext.xml");