Maven,主要是一个jar包管理仓库和项目构建,了解了常用框架*
- 前端:jquery easyui bootstrap amazeui
- java后台:struts1 struts2 springmvc(流程控制框架);hibernate mybatis springdata(持久层框架);spring ( 一站式框架)
- 技术选型: spring+springmvc +hibernate;spring+springmvc +mybatis;spring+struts2+hibernate
- 权限管理:shrio springsecurity
- 数据存储:redis mongodb
1、 maven安装
①检查JAVA_HOME环境变量
C:\Windows\System32>echo %JAVA_HOME%
D:\DevInstall\jdk1.7.0_07
②解压Maven的核心程序
将apache-maven-3.2.2-bin.zip解压到一个非中文无空格的目录
③配置环境变量
M2_HOME D:\DevInstall\apache-maven-3.2.2
path .....;D:\DevInstall\apache-maven-3.2.2\bin
④查看Maven版本信息验证安装是否正确
命令行中输入命令:mvn -v(注意:v一定不能大写)
2、约定的目录结构
我们可以通过Maven命令来自动生成一个按照约定目录的项目骨架,步骤入下
命令行中输入mvn archetype:generate
在执行过程中停止到Choose a number or apply filter按回车键继续
输入自定义文字groupid (一般是公司域名)
输入自定义文字artifactid (项目名称)
输入自定义文字version (项目版本)
输入自定义文字package (创建项目默认的包名)
确认之后输入Y开始创建。
执行完毕之后在本地文件夹 c/user/ artifactid 下中便创建了按照约定目录的maven项目
3、jar包坐标定位
①用http://mvnrepository.com/直接搜索,复制里面的定位文件放到pom.xml里dependencies下
version:当前模块的版本 3.2.3 beta
beta(公测)
SNAPSHOT 快照 ,内侧版本
release 发布版本
Hibernate
1、Hibernate是一款工作在持久化层的大型、开源、免费的ORM框架。
①将对数据库的操作转换为对象Java对象的操作,从而简化开发。通过修改一个“持久化”对象的属性从而修改数据库表中对应的记录数据。通过操作对象达到数据库的目的。
②提供线程和进程两个级别的缓存提升应用程序性能。
缓存:查询出来数据之后在缓存中进行保存,下次查询相同数据直接从缓存中读取,减少数据库操作
③有丰富的映射方式将Java对象之间的关系转换为数据库表之间的关系。
④屏蔽不同数据库实现之间的差异。在Hibernate中只需要通过“方言”的形式指定当前使用的数据库,就可以根据底层数据库的实际情况生成适合的SQL语句。
例如:
MySQL分页:LIMIT
Oracle分页:ROWNUM
2、对象关系映射
①概念:Object/Relationship Mapping,对象关系映射
②对象:Java程序中用于封装业务数据的对象。通常称为实体类(Entity),以JavaBean(POJO)技术实现。例如:Book 、User、Person等等这样的类的对象。
③关系:关系型数据库,目前主流的数据库都是关系型的。
④映射:建立从“对象”到“关系型数据库”之间的对应关系。
简单的说:
使用一个pojo类表示一张表的结构,这个动作就是映射。
3、Hibernate搭建环境
①导入Hibernate需要的JAR包
②导入数据库驱动
③创建Hibernate自身的配置文件:hibernate.cfg.xml
④创建持久化类PO Persistence Object (POJO类,实体类,数据模型类)
⑤创建持久化类对应的关系映射文件:Student.hbm.xml文件
⑥在hibernate.cfg.xml文件中声明映射文件的位置(在3中完成)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/1702shop</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123</property>
<!-- 配置连接数据库所需要的常量 这些常量提供给hibernate连接数据库使用
show_sql 我们是操作对象,看不到sql语句,我们可以通过设置show_sql,
hibernate运行操作数据库会把执行需要的sql语句输出到控制台中 --><property name="show_sql">true</property>
<!--自动创建|更新|验证数据库表结构,自动建立起表的结构,model类自动更新表结构-->
<property name="hibernate.hbm2ddl.auto" value=”update" />
</session-factory>
</hibernate-configuration>
创建持久化类
参照表结构创建对应的pojo对象
表-> 类
字段->属性
字段sql类型->属性java类型
要求类需要有oid属性,相当于一个表需要有主键一样
Person.hbm.xml实体类配置文件
[1]创建位置:和持久化类在同一个包下
[2]创建名称:pojo类名.hbm.xml
用于声明类与表,属性与字段之间关系的配置文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-6-7 12:16:56 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<!-- name实体类的包名+类名, table 就是表名 -->
<class name="com.qianfeng.Users" table="USERS">
<!-- 属性名设置为id,hibernate默认会把它当做主键 -->
<!-- name代表类的属性名 ,type是属性的类型 -->
<id name="id" type="int">
<generator class="native" />
</id>
<!-- property表示普通字段 -->
<property name="username" type="java.lang.String">
<column name="USERNAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
</class>
</hibernate-mapping>
hibernate.cfg.xml中声明hbm.xml文件的位置
- 在hibernate配置文件中除了设置链接数据库相关信息之外,还需要添加关联到hbm.xml文件。一般来说每一个想要通过hibernate操作的表都会有对应类,那么每一个都有对应的hbm.xml文件,hiernate.cfg.xml也就有对应每一个的映射声明。
<mapping resource="com/atguigu/bean/Student.hbm.xml" />
hibernate中session和JDBC区别
代表Hibernate应用程序和数据库之间的一次会话,作用相当于JDBC中的Connection。其中封装了操作一系列方法操作数据库并包含缓存功能
SessionFactory
用于创建Session对象的工厂类。
特点:
1SessionFactory对象一旦构造完毕,即被赋予特定的配置信息。
2构造SessionFactory很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory对象。
3Hibernate4新增了一个ServiceRegistry 接口,所有基于Hibernate的配置或者服务都必须统一向这个ServiceRegistry注册后才能生效。
创建SessionFactory对象的步骤
[1]创建封装配置信息的Configuration对象。
[2]在ServiceRegistry对象中注册配置信息。
[3]通过Configuration对象构建SessionFactory对象。
- 主要代码
①测试目标:使用Hibernate实现将Student对象保存到数据库中。
②实现步骤
[1]创建SessionFactory对象
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder builder = new ServiceRegistryBuilder();
builder.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = builder.buildServiceRegistry();
SessionFactory factory = configuration.buildSessionFactory(serviceRegistry);
[2]通过SessionFactory对象创建Session对象,也就是开启和数据库之间的一次会话
Session session = factory.openSession();
[3]开启事务
Transaction transaction = session.beginTransaction();
[4]执行操作
Student student = new Student(null, "Tom2015", 20, new Date());
session.save(student);
[5]提交事务
transaction.commit();
[6]关闭Session
session.close();
[7]关闭SessionFactory
factory.close();
- 4.x版本与5.x版本
Hibernate各个版本对sessionFactory对象的初始化代码并不一样,以上代码是依照4.0的版本。
以下是5.x对sessionFactyory对象的初始化方式,其他使用基本一样
//但在5.1.0版本汇总,hibernate则采用如下新方式获取:
//1. 配置类型安全的准服务注册类,这是当前应用的单例对象,不作修改,所以声明
为final //在configure(“cfg/hibernate.cfg.xml”)方法中,如果不指定资源路径,
默认在类路径下寻找名为hibernate.cfg.xml的文件
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("cfg/hibernate.cfg.xml").build();
//2. 根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
数据库表生成策略
①概述
Hibernate在创建SessionFactory对象时,会根据*.hbm.xml映射文件中的信息自动生成对应的数据库表,而在生成数据库表的过程中,可以根据不同的配置信息采取不同的生成策略。
②配置方式
在hibernate.cfg.xml配置文件中加入如下配置
<property name="hbm2ddl.auto">update</property>
③可以选择的生成策略
- [1]create:根据*.hbm.xml文件生成新的数据库表,而且是每一次运行都删除旧表创建新的表,即使两次操作的过程中数据库表没有任何改变
- [2]update:按照如下几种情况生成数据库表
<1>数据库表不存在:生成新的数据库表
<2>数据库表存在且表结构不需要改变:保留原来的数据库表
<3>数据库表存在但表结构有变化:在原来数据库表的基础上更新数据库表,不会删除原有的行和列 - [3]create-drop:每一次运行都生成新的数据库表,并在执行操作后将表删除
[4]validate:会和数据库中的表进行比较,若*.hbm.xml文件中的列在数据表中不存在,则抛出异常
Session与缓存
Session接口是Hibernate向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存、
更新、删除和加载Java对象的方法。
每一个Session对象都在内存中维护了一个缓存,我们叫他一级缓存。
两次调用session.get(Student.class,1);方法,仅发送1条SQL语句。原因是第一次
使用get()方法加载的Student被缓存到了内存中,第二次调用get()方法直接使用了
内存中缓存的Student对象,从而减少了访问数据库的次数。
持久化对象状态
一般我们认为有三种但也有说四种的
- 临时状态
由java的new命令开辟内存空间的java对象也就是普通的java对象,如果没有变量引用它它将会被JVM收回。临时对象在内存中是孤立存在的,它的意义是携带信息载体,不和数据库中的数据由任何的关联。通过Session的save()方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映射插入数据库中,这个临时对象就成为持久化对象。 - 持久化状态:
持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的session声明周期中保存这个状态。如果是直接数据库查询所返回的数据对象,则这些对象和数据库中的字段相关联,具有相同的id,它们马上变成持久化对象。如果一个临时对象被持久化对象引用,也立马变为持久化对象。 - 游离状态
Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,可以继续对这个对象进行修改,如果脱管对象被重新关联到某个新的Session上,会在此转成持久对象。
4.hibernate中的表关系
- 一对多
- 一对一
user id name age tel mobile chanzhen adress city country
数据库中有一个表为user。需要保存用户信息,包括id,名称,性别,座机,手机,传真等。其中座机,手机,传真我们可以单独提取出来一张联系方式表。
故当涉及到一个具体实体的信息量较多,或者可以分类的时候,就可以使用了1-1,当然只要你能把一个实体的关系拆分成几个有归类的部分也可以适用。
如果都放在一张表里,一:不便于管理(包括查询执行速度),二:也就达不到关系型数据库的原子性特性。
1对1需要主键和外键
比如:
经理与部门的关系实现。
经理表manager
部门department表
如果想要确定一个部门的经理是谁,我们可以在经理表中添加外键指向部门表的主键来实现。
实现方式:
Department表的主键作为外键关联到Manager表。意思是department表的主键不是像之前我们常用的自增,因为是1对1所以Department的主键又充当外键关联manager
2映射文件1
department
<class name ="Department" table="DEPARTMENTS">
<id name ="deptId" type="java.lang.Integer">
<column name ="DEPT_ID" />
<!-- 设置当前表的主键列依赖另外一张表的主键实现 -->
<generator class ="foreign">
<param name ="property">manager</ param>
</generator >
</id >
<property name ="deptName" type="java.lang.String">
<column name ="DEPT_NAME" />
</property >
<!-- 使用constrained属性给生成的主键列加上外键约束 -->
<one-to-one name ="manager" class="Manager" constrained= "true" />
</class >
2映射文件
manager
<class name ="Manager" table="MANAGERS">
<id name ="mngId" type="java.lang.Integer">
<column name ="MNG_ID" />
<generator class ="native" />
</id >
<property name ="mngName" type="java.lang.String">
<column name ="MNG_NAME" />
</property >
<one-to-one name ="department" class="Department" />
</class >
- 多对一
n对1
1对n
双向1对n
首先什么是多对一,多对一的场景
- 现有两张表,users和score。Users表保存所有学生信息,score表保存所有学生所有课程的成绩。那么现在users表和score表就构成了一对多的关系。因为一个学生可以考试多门成绩,也就是说在users表中的一条记录表示的学生在score表中有多条对应的考试成绩记录。
一个学生可以有多个成绩,故:
Users (一) ----》score(多)一对多关系
思考还有其他场景也符合多对一关系?
实现:
1分别创建持久化类
2创建对应的*.hbm.xml映射文件
3添加映射关系配置信息(额外的表示关系的配置)
单向多对一:
创建持久化类:
①one:Customer
封装自身必要的信息即可,不包含Order集合的引用
②many:Order
除了要封装自身相关的信息,还要包含Customer对象的引用,属性中无需出现外键字段
创建*.hbm.xml映射文件
one:Customer.hbm.xml
简单的单表映射(xml内容略)
many:Order.hbm.xml
[1]映射OID和自身信息
[2]映射many-to-one关联关系
属性说明:
Name: Order类中Customer属性名。
Class:Customer类的类名(完整的是包名+类名)
Column:order表中外键的字段名
多对多
- 场景举例:
学生和选修课程,一个学生可以选修多门课程,一个课程也可以拥有多个学生。
电影和演员,一个演员可以参演多个电影,一部电影有很多演员。
用户和权限组,一个用户可以有都个权限,拥有一个权限的有很多用户。
5.hibernate中三种检索方式
-
hql
在SQL中,FROM子句是用于指定要查询的数据库表,在HQL中,替换为与数据库表对应的Java实体类即可
例如: SQL SELECT * FROM EMPS HQL FROM Employee
和SQL的语法一样,HQL中的WHERE子句也用来指定查询条件。只不过这里指定查询条件使用的不是数据库表的字段,而是Java类的属性。
SQL
SELECT * FROM EMPS WHERE EMPS.SALARY>5000
HQL
FROM Employee e WHERE e.salary>5000
将上例中的具体值使用占位符“?”代替,并调用Query对象的setXxx()方法按照参数的不同类型动态填充即可,需要注意的是和JDBC中的PreparedStatement接口不同,这里占位符的索引从0开始。
HQL
FROM Employee e WHERE e.salary>?
填充占位符
query.setDouble(0, 8000.00);
- 在HQL中不但能够使用基于位置的占位符参数,还能够使用基于名称的具名参数,使用具名参数的好处是不必关心当前参数的索引值。
具名参数的格式是:“:参数名称”。
例如: HQL FROM Employee e WHERE e.salary>:salaryParam
使用ORDER BY子句可以进行排序
HQL FROM Employee e WHERE e.salary>:salaryParam ORDER BY e.salary DESC
和SQL一样,默认按照升序排列。DESC表示降序,ASC表示升序。
分页查询是HQL的一大亮点,不必关心底层数据库的具体实现是什么,使用HQL调用固定的方法就能够实现垮数据库平台的分页查询。(mysql和orcal实现分页关键词不同)
在分页时我们需要指定两个最基本的数据,一个是当前页的页码:pageNo,一个是每页显示多少条数据:pageSize。
下面列出了Query接口中与分页相关的两个函数
setFirstResult(int index)相当于offset
指定查询结果从index位置开始取,index从0开始
setMaxResults(int maxResults) 相当于limit
指定查询结果取maxResults条数据
index和pageNo的关系是:index=(pageNo-1)*pageSize(pageNo:当前页的页码; pageSize:每页显示数据的数量)
所谓投影查询其实就是仅查询实体类对象的部分字段,这里用到了HQL语句的SELECT关键词。
SELECT e.empName,e.salary From Employee e WHERE e.salary>9000
那么此时的查询结果以什么形式返回呢?
HQL并没有将使用空的Employee对象接收empName和salary的值,而是把它们放在了一个Object数组中。
Query query = session.createQuery(queryString);
List<Object[]> list = query.list();
for (Object[] objects : list) {
System. out.println(objects[0]+" "+objects[1]);
}
接收投影查询结果可以仍然使用实体类的对象,但要求实体类中提供对应的构造器。
HQL
SELECT new Employee(e.empName,e.salary) From Employee e 这样得到的每一条数据都将被封装到Employee对象中。
HQL:
select s.id,s.name,sc.score from Student as s,Score as sc where s.id = sc.user.userId;
上面字段都是 javabean的属性,其他与sql语句类似。
返回类型List<object[]>数组
from a,b where a.id=b.a_id
from a inner jion b on a.id=b.a_id
form a left outer jion b on a.id=b.a_id
全连接
full jion ,但是mysql不支持这种写法,可以使用union来吧左外和右外的结果拼接成一个结果集,union会去除重复数据。这样就得到了一个全连接结果,也就是包含左表和右表全部数据。
union all也是拼接结果集,但是不进行去重
和SQL一样,HQL也使用GROUP BY和HAVING子句配合起来进行分组,再结合统计函数进行报表查询。
SELECT min(e.salary),max(e.salary)
From Employee e
GROUP BY e.department
HAVING min(e.salary)>3000
(每)
min()和max()统计函数的结果最终被放在了一个Object数组中。
- 子查询是SQL语句中非常重要的功能,它可以在SQL语句中利用另外一条SQL语句的查询结果。HQL同样对子查询功能提供了支持。与SQL子查询不同的是,HQL不支持在FROM子句中使用子查询。
查询部门名以“A”开头的部门的员工姓名
select e.empName,e.department
from Employee e
where e.department in
(From Department d where d.deptName like 'A%')
删除数据
HQL
Delete From Employee e WHERE e.empId=117
session.createQuery(queryString).executeUpdate()
更新数据
HQL
UPDATE Employee e Set e.empName=’Tom’ WHERE e.empId=115
session.createQuery(queryString).executeUpdate()
-
原生sql
有些情况下我们需要直接执行原始的SQL语句,这时可以使用session对象创建SQLQuery对象,并调用list()或uniqueResult()方法返回查询结果,如果是执行增删改操作,可以调用executeUpdate()方法。
List cats= sess.createSQLQuery(" select * from cats " ).addEntity(Cat. class).list();
addEntity()方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。
-
qbc
QBC查询就是通过使用Hibernate提供的Query By Criteria API来查询对象,这种API 封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口。
- 1创建Criteria对象
Criteria criteria = session.createCriteria(Employee.class);
创建Criteria对象,类似于HQL查询中创建Query对象,只不过Criteria对象和Query对象的用法差别很大。
Criteria对象可以通过session对象的createCriteria()方法创建,创建时需要提供目标持久化类的Class类对象(即目标持久化类)。
- 取得查询结果
Criteria criteria = session.createCriteria(Employee.class);
List<Employee> list = criteria.list();
Criteria对象大体上有两种方式获取查询结果:list()方法和uniqueResult()方法。list()方法获取多条记录的查询结果,uniqueResult()方法获取单一记录的查询结果。
这个例子表示不带任何查询条件,查询全部Employee对象,并返回全部Employee对象组成的List集合。
- QBC查询最大的特点是可以将SQL语句中的查询条件以面向对象的方式封装起来,并根据封装好的查询条件返回结果。
封装查询条件要用到Restrictions类的各个静态方法
封装查询条件之后,上述静态方法都会返回一个Criterion接口的实例,拿到这个Criter
ion对象后可以将其添加到Criteria对象中。
例如:
Criterion like = Restrictions.like("empName","%a%");
Criterion gt = Restrictions.gt("salary",9000.00);
List<Employee> list = criteria
.add(like)
.add(gt)
.list();
其中add()方法也支持连缀调用。
- 在QBC API中使用Conjunction类表示AND,使用Disjunction表示OR,它们都可以连接Criterion对象生成AND或OR语句。
Criterion like = Restrictions. like(“empName”, “%a%”);
Criterion gt = Restrictions. gt(“salary”, 9000.00);
//创建AND条件对象
Conjunction conjunction = Restrictions.conjunction();
//使用AND连接like和 gt
conjunction.add(like).add(gt);
List<Employee> list = session.createCriteria(Employee.class)
.add(conjunction)
.list();
甚至AND和OR作为整体也可以连接在一起
Conjunction conjunction01 = Restrictions.conjunction();
Conjunction conjunction02 = Restrictions.conjunction();
Disjunction disjunction = Restrictions.disjunction();
//( and ) or ( and )
disjunction.add(conjunction01).add(conjunction02);
- 在QBC查询中可以使用Projections类的静态方法封装SQL中的统计函数
AggregateProjection max = Projections.max("salary");
criteria.setProjection(max);
如果有多个统计函数需要执行,则创建ProjectionList对象,用于包含多个Projection对象
AggregateProjection max = Projections.max("salary");
AggregateProjection min = Projections.min("salary");
ProjectionList projectionList = Projections.projectionList();
projectionList.add(max).add(min);
List<Object[]> list = session.createCriteria(Employee.class)
.setProjection(projectionList)
.list();
可以使用groupProperty(String propertyName)方法对查询结果进行分组
Criteria criteria = session.createCriteria(Employee.class);
PropertyProjection groupProperty = Projections.groupProperty("department");
criteria.setProjection(groupProperty).list();
Order asc = Order.asc("salary");
Order desc = Order.desc("empName");
List<Employee> list = session.createCriteria(Employee.class)
.addOrder(asc)
.addOrder(desc)
.list();
QBC分页和HQL分页的操作大体上是一致的
int pageNo = 2;
int pageSize = 5;
List<Employee> list = session.createCriteria(Employee.class)
.setFirstResult((pageNo - 1)*pageSize)
.setMaxResults(pageSize)
.list();
6.检索策略
-
立即检索策略
采用立即检索策略,会将被检索的对象,以及和这个对象关联的一对多对象都加载到缓存中。Session的get方法就使用的立即检索策略。
-
优缺点
优点:频繁使用的关联对象能够被加载到缓存中。
缺点:1、占用内存。2、Select语句过多。
-
延迟检索策略
在类级别操作时, 延迟检索策略,只加载类的OID不加载类的其他属性,只用当第一次访问其他属性时,才回访问数据库去加载内容。(Load方法与get方法的区别)
- 在关联级别操作时,延迟检索策略,只加载类本身,不加载关联类,直到第一次调用关联对象时,才去加载关联对象(默认)
-
优缺点
优点:由程序决定加载哪些类和内容,避免了大量无用的sql语句和内存消耗。
缺点:在Session关闭后,就不能访问关联类对象了。 需要确保在Session.close方法前,调用关联对象。
-
有关延时和禁止延时的配置
1.若lazy存在class标记中使用lazy那么可选值是true/false,分别是使用延迟和禁止使用
2.lazy还可以出现杂set标签中,那么可选值是三个true/false/extra
true:
默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其
集合元素的数据
false:
取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
extra:
一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据
3.lazy还可以存在于many-to-one标记中可选值有false/proxy/no-proxy。
默认值是proxy表示延迟加载,false表示不延迟加载。