Mysql分页采用limt关键字
select * from t_order limit 5,10; #返回第6-15行数据
select * from t_order limit 0,5; #返回前5行
Mssql 2000分页采用top关键字(20005以上版本也支持关键字rownum)
Select top 10 * from t_order where id not in (select id from t_order where id>5 ); //返回第6到15行数据
其中10表示取10记录 5表示从第5条记录开始取
Oracle分页
①采用rownum关键字(三层嵌套)
SELECT * FROM(
SELECT A.*,ROWNUM num FROM
(SELECT * FROM t_order)A
WHERE
ROWNUM<=15)
WHERE num>=5;--返回第5-15行数据
②采用row_number解析函数进行分页(效率更高)
SELECT xx.* FROM(
SELECT t.*,row_number() over(ORDER BY o_id)AS num
FROM t_order t
)xx
WHERE num BETWEEN 5 AND 15;
--返回第5-15行数据
解析函数能用格式
函数() over(pertion by 字段 order by 字段);
Pertion 按照某个字段分区
Order 按照勒个字段排序
2.mysql数据库索引
索引分为
-
主键索引 一个列为设置为主键会默认创建一个主键索引。
-
唯一索引 严格来说主键索引是唯一索引的一种,这两个的区别是:主键索引不允许为null,唯一索引可以为null;
-
单列索引
-
复合索引
什么是索引
索引就是一种优化查询的数据结构;
为什么用索引
因为创建索引可以大大提高系统的查询性能。
数据库事务的目的
所谓事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。例如,在关系数据库中,一个事务可以是一条SQL语句、一组SQL语句或整个程序。
简单举个例子就是你要同时修改数据库中两个不同表的时候,如果它们不是一个事务的话,当第一个表修改完,可是第二表改修出现了异常而没能修改的情况下,就只有第二个表回到未修改之前的状态,而第一个表已经被修改完毕。
而当你把它们设定为一个事务的时候,当第一个表修改完,可是第二表改修出现了异常而没能修改的情况下,第一个表和第二个表都要回到未修改的状态!这就是所谓的事务回滚
3.java面向对象的三大基本特征
一、封装
1、概念:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
2、好处:
-
只能通过规定的方法访问数据。
-
隐藏类的实例细节,方便修改和实现。
3、封装的实现步骤
需要注意:对封装的属性不一定要通过get/set方法,其他方法也可以对封装的属性进行操作。当然最好使用get/set方法,比较标准。
A、访问修饰符
从表格可以看出从上到下封装性越来越差。
B、this关键字
1.this关键字代表当前对象
this.属性 操作当前对象的属性
this.方法 调用当前对象的方法。
2.封装对象的属性的时候,经常会使用this关键字。
3.当getter和setter函数参数名和成员函数名重合的时候,可以使用this**区别。如:**
C、Java 中的内部类
内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。
那么问题来了:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多好啊!!
答:内部类的主要作用如下:
-
内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
-
内部类的方法可以直接访问外部类的所有数据,包括私有的数据。
-
内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。
内部类可分为以下几种:
-
-
成员内部类
-
静态内部类
-
方法内部类
-
匿名内部类
-
二、继承
1、继承的概念
继承是类与类的一种关系,是一种“is a”的关系。比如“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。如下图所示:
注:java中的继承是单继承,即一个类只有一个父类。
2、继承的好处
子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用;
3、语法规则,只要在子类加上extends关键字继承相应的父类就可以了:
A、方法的重写
子类如果对继承的父类的方法不满意(不适合),可以自己编写继承的方法,这种方式就称为方法的重写。当调用方法时会优先调用子类的方法。
重写要注意:
a、返回值类型
b、方法名
c、参数类型及个数
都要与父类继承的方法相同,才叫方法的重写。
重载和重写的区别:
方法重载:在同一个类中处理不同数据的多个相同方法名的多态手段。
方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改。
B、继承的初始化顺序
1、初始化父类再初始化子类
2、先执行初始化对象中属性,再执行构造方法中的初始化。
基于上面两点,我们就知道实例化一个子类,java程序的执行顺序是:
父类对象属性初始化---->父类对象构造方法---->子类对象属性初始化--->子类对象构造方法
下面有个形象的图:
C、final关键字
使用final关键字做标识有“最终的”含义。
-
final 修饰类,则该类不允许被继承。
-
final 修饰方法,则该方法不允许被覆盖(重写)。
-
final 修饰属性,则该类的该属性不会进行隐式的初始化,所以 该final 属性的初始化属性必须有值,或在构造方法中赋值(但只能选其一,且必须选其一,因为没有默认值!),且初始化之后就不能改了,只能赋值一次。
-
final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量。
D、super关键字
在对象的内部使用,可以代表父类对象。
1、访问父类的属性:super.age
2、访问父类的方法:super.eat()
super的应用:
首先我们知道子类的构造的过程当中必须调用父类的构造方法。其实这个过程已经隐式地使用了我们的super关键字。
这是因为如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。
那么如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行。
要注意的是:如果子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则编译出错。
(补充说明,虽然没有显示声明父类的无参的构造方法,系统会自动默认生成一个无参构造方法,但是,如果你声明了一个有参的构造方法,而没有声明无参的构造方法,这时系统不会动默认生成一个无参构造方法,此时称为父类有没有无参的构造方法。)
E、Object类
Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另一个类,那么这个类默认继承Object类。
Object类中的方法,适合所有子类!!!
那么Object类中有什么主要的方法呢?
1、toString()
a. 在Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串)。
我们可以发现,如果我们直接用System.out.print(对象)输出一个对象,则运行结果输出的是对象的对象地址字符串,也称为哈希code码。如:
哈希码是通过哈希算法生成的一个字符串,它是用来唯一区分我们对象的地址码,就像我们的身份证一样。
b. 可以通过重写toString()方法表示出对象的属性。
如果我们希望输出一个对象的时候,不是它的哈希码,而是它的各个属性值,那我们可以通过重写toString()方法表示出对象的属性。
2、equals()
a、equals()----返回值是布尔类型。
b、默认的情况下,比较的是对象的引用是否指向同一块内存地址-------对象实例化时,即给对象分配内存空间,该内存空间的地址就是内存地址。使用方法如:dog.equals(dog2);
c、 如果是两个对象,但想判断两个对象的属性是否相同,则重写equals()方法。
以Dog类为例,重写后的equals()方法如下(当然你可以根据自己想比较的属性来重写,这里我以age属性是否相同来重写equals()方法):
上面有四个判断,它们的含义分别是:
1.判断地址是否相同----if (this == obj),相同则返回true
2.判断对象是否为空----if (obj == null),为空则返回false
3.getClass()可以得到类对象,判断类型是否一样-----if (getClass() != obj.getClass()),不一样则返回false
4.判断属性值是否一样----if (age != other.age),不一样返回false
5.如果地址相同,对象不为空,类型一样,属性值一样则返回true
这里要注意的是,理解obj.getClass()得到的类对象和类的对象的区别,以下用图形表示:
可以看到,对于类对象我们关心它属于哪个类,拥有什么属性和方法,比如我和你都是属于“人”这个类对象;而类的对象则是一个类的实例化的具体的一个对象。比如我和你是两个不同的人。
三、多态
面向对象的最后一个特性就是多态,那么什么是多态呢?多态就是对象的多种形态。
java里的多态主要表现在两个方面:
1.引用多态
父类的引用可以指向本类的对象;
父类的引用可以指向子类的对象;
2.方法多态
根据上述创建的两个对象:本类对象和子类对象,同样都是父类的引用,当我们指向不同的对象时,它们调用的方法也是多态的。
创建本类对象时,调用的方法为本类方法;
创建子类对象时,调用的方法为子类重写的方法或者继承的方法;
使用多态的时候要注意:如果我们在子类中编写一个独有的方法(没有继承父类的方法),此时就不能通过父类的引用创建的子类对象来调用该方法!!!
注意: 继承是多态的基础。
B、抽象类
定义:抽象类前使用abstract关键字修饰,则该类为抽象类。
使用抽象类要注意以下几点:
-
抽象类是约束子类必须有什么方法,而并不关注子类如何实现这些方法。
-
抽象类应用场景:
a. 在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法(可实现动态多态)。
b. 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免子类设计的随意性。
-
抽象类定义抽象方法,只有声明,不需要实现。抽象方法没有方法体以分号结束,抽象方法必须用abstract关键字来修饰。如:
4、包含抽象方法的类是抽象类。抽象类中可以包含普通的方法,也可以没有抽象方法。如:
5、抽象类不能直接创建,可以定义引用变量来指向子类对象,来实现抽象方法。以上述的Telephone抽象类为例:
C、接口
1、概念
接口可以理解为一种特殊的类,由全局常量和公共的抽象方法所组成。也可理解为一个特殊的抽象类,因为它含有抽象方法。
如果说类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供的某些方法。(这里与抽象类相似)
常用的集合有哪些
1 Set
1) Set 集合属于单列集合,不允许包含重复元素; 2) 判断元素是否重复的标准为对象的 equals 方法,存在时返回 false,不存在返回 true; 3) 元素的排序规则,由相应的实现类决定,分为无序、元素大小排序、写入顺序排序; 4) 初始化大小,扩容参考 HashMap。
1.1 Set 接口、实现类:
名称 类型 线程同步 描述 Set 接口 继承了Collection接口 SortedSet 接口 继承了Set接口 HashSet 实现类 不同步 继承了AbstractSet类,实现了Set、Cloneable、Serializable接口 TreeSet 实现类 不同步 继承了AbstractSet类,实现了NavigableSet(继承了SortedSet)、Cloneable、Serializable接口 LinkedHashSet 实现类 不同步 继承了HashSet类,实现了Set、Cloneable、Serializable接口
1.2 HashSet
1) HashSet 实现了 Set 接口,继承了 AbstractSet 类,由哈希表支持,看源码可以发现是一个 HashMap 实例。 2) HashSet 不保证集合内元素的迭代顺序,特别是不保证迭代顺序永久不变,该集合运行 null 元素存在。 3) HashSet 中的元素,作为 HashMap 键值对的 Key 存储,而 Value 由一个统一的值保存。 4) HashSet 默认初始化大小为 16,扩容加载因子为 0.75,扩容大小为原来的一倍。即一个初始化size为16的 HashSet,元素添加到12个的时候会进行扩容,扩容后的大小为32。 备注:具体添加、读取、删除等规则需要参考 HashMap 的具体实现。
1.3 TreeSet
1) TreeSet 实现了 NavigableSet 接口,继承了AbstractSet类,由哈希表支持,看源码可以发现是一个 TreeMap 实例。 2) TreeSet 中的元素有序的,排序规则遵照元素本身的大小进行排序,元素不能重复。 3) TreeSet 中的元素,作为 TreeMap 键值对的 Key 存储,而 Value 由一个统一的值保存。 备注:具体添加、读取、删除等规则需要参考 TreeMap 的具体实现。
1.4 LinkedHashSet
1) LinkedHashSet 实现了 Set 接口,继承了HashSet类,由哈希表支持,看源码可以发现是一个 LinkedHashMap 实例。 2) LinkedHashSet 中的元素有序的,排序规则遵照元素写入顺序进行排序,元素不能重复。 3) LinkedHashSet 中的元素,作为 LinkedHashMap 键值对的 Key 存储,而 Value 由一个统一的值保存。 备注:具体添加、读取、删除等规则需要参考 LinkedHashMap、HashMap 的具体实现,LinkedHashMap继承了HashMap。
1.5 线程安全
由于 HashSet、TreeSet、LinkedHashSet的底层实现为HashMap、TreeMap、LinkedHashMap,所以Set集合是非线程安全的。 如果要实现 Set 集合的线程安全,可以使用 ConcurrentHashMap 实现一个Set集合。
2 List
1) List 集合属于单列、有序的、允许元素重复、可以为 null 的集合; 2) List 接口的实现类主要有三种:ArrayList、LinkedList、Vector。
2.1 List 接口、实现类:
名称 类型 线程同步 描述 List 接口 继承了Collection接口 ArrayList 实现类 不同步 继承了AbstractList类,实现了List、RandomAccess、Cloneable、Serializable接口 LinkedList 实现类 不同步 继承了AbstractSequentialList类,实现了List、Deque、Cloneable、Serializable接口 Vector 实现类 同步 继承了AbstractList类,实现了List、RandomAccess、Cloneable、Serializable接口
2.2 ArrayList
1) ArrayList 实现了 List 接口,继承了 AbstractList 类,由一个 Object[] 实例实现,即底层为数组结构; 2) 默认初始化长度为 10,扩容规则为 0.5倍的原容量加1,即一次扩容后的长度为 16; 3) 特点:查询速度快,添加、删除相对于LinkedList较慢、线程不同步(不安全)。
2.2 LinkedList
1) LinkedList 实现了 List 接口,继承了 AbstractSequentialList 类,由一个 Node 节点链表实现,即底层为链表结构; 2) 由于LinkedList 数据结构为链表,无预扩容机制; 3) 特点:添加、删除速度快,查询相对于ArrayList较慢、线程不同步(不安全)。
2.3 Vector
1) Vector实现了 List 接口,继承了 AbstractList 类,由一个 Object[] 实例实现,即底层为数组结构; 2) 默认初始化长度为 10,扩容加载因子为 1,当元素长度大于原容量时进行扩容,默认为 10,一次扩容后容量为 20; 3) 特点:线程安全,但是速度慢;在实现的方法上,用 synchronized 关键字进行了修饰,即在方法上实现了同步锁。 备注:具体实现细节请查看源码。
3 Map
1) Map 集合属于双列Key-value键值对的集合,Key不允许重复,是否允许为 null 根据实现类而定,Value 随意; 2) Map 接口的实现类主要有三种:HashMap、LinkedHashMap、TreeMap、Hashtable、ConcurrentHashMap。
3.1 Map 接口、实现类:
名称 类型 线程同步 描述 Map 接口 HashMap 实现类 不同步 继承了AbstractMap类,实现了Map、Cloneable、Serializable接口 LinkedHashMap 实现类 不同步 继承了HashMap类,实现了Map接口 TreeMap 实现类 不同步 继承了AbstractMap类,实现了NavigableMap(继承了SortedMap)、Cloneable、 Serializable接口 Hashtable 实现类 同步 继承了Dictionary类,实现了Map、Cloneable、Serializable接口 ConcurrentHashMap 实现类 同步 继承了AbstractMap类,实现了ConcurrentMap(继承了Map)、Serializable接口
3.2 HashMap
1) HashMap实现了 Map接口,继承了 AbstractMap类,数据结构采用的位桶数组,底层采用链表或红黑树进行存储; 2) 默认初始化长度为 16,扩容加载因子为 0.75,一旦大于 0.75*16之后,就会调用resize()进行扩容,扩容2倍,即32; 3) JDK1.7中,数据结构采用:位桶数组+链表结构; JDK1.8中,数据结构采用:位桶数组+(链表/红黑树); 4) 支持克隆,无序,线程不同步,非安全。
3.3 LinkedHashMap
1) LinkedHashMap 实现了 Map 接口,继承了 HashMap 类; 引用实现; 3) 迭代顺序由 accessOrder 属性的决定,默认为 false,以插入顺序访问;设置为 true 则按上次读取顺序访问(每次访问 元素时会把元素移动到链表末尾方便下次访问,结构会时刻变化)。 4) 默认初始化长度为 16,扩容加载因子为 0.75,一旦>0.75*16之后,就会调用resize()进行扩容,与HashMap一致; 5) 支持克隆,有序,线程不同步,非安全。
java的八大数据类型
byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。
short:16位,最存储量是65536,数据范围是-32768~32767之间。
int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有true和false两个取值。
char:16位,存储Unicode码,用单引号赋值。
Java决定了每种简单类型的大小。这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。下表列出了Java中定义的简单类型、占用二进制位数及对应的封装器类。
简单类型 | boolean | byte | char | short | Int | long | float | double | void |
---|---|---|---|---|---|---|---|---|---|
二进制位数 | 1 | 8 | 16 | 16 | 32 | 64 | 32 | 64 | -- |
封装器类 | Boolean | Byte | Character | Short | Integer | Long | Float | Double | Void |
对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。如:
基本类型byte 二进制位数:Byte.SIZE最小值:Byte.MIN_VALUE最大值:Byte.MAX_VALUE
基本类型short二进制位数:Short.SIZE最小值:Short.MIN_VALUE最大值:Short.MAX_VALUE
基本类型char二进制位数:Character.SIZE最小值:Character.MIN_VALUE最大值:Character.MAX_VALUE
基本类型double 二进制位数:Double.SIZE最小值:Double.MIN_VALUE最大值:Double.MAX_VALUE
注意:float、double两种类型的最小值与Float.MIN_VALUE、 Double.MIN_VALUE的值并不相同,实际上Float.MIN_VALUE和Double.MIN_VALUE分别指的是 float和double类型所能表示的最小正数。也就是说存在这样一种情况,0到±Float.MIN_VALUE之间的值float类型无法表示,0 到±Double.MIN_VALUE之间的值double类型无法表示。这并没有什么好奇怪的,因为这些范围内的数值超出了它们的精度范围。
Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。
Java基本类型存储在栈中,因此它们的存取速度要快于存储在堆中的对应包装类的实例对象。从Java5.0(1.5)开始,JAVA虚拟机(Virtual Machine)可以完成基本类型和它们对应包装类之间的自动转换。因此我们在赋值、参数传递以及数学运算的时候像使用基本类型一样使用它们的包装类,但这并不意味着你可以通过基本类型调用它们的包装类才具有的方法。另外,所有基本类型(包括void)的包装类都使用了final修饰,因此我们无法继承它们扩展新的类,也无法重写它们的任何方法。
基本类型的优势:数据存储相对简单,运算效率比较高
包装类的优势:有的容易,比如集合的元素必须是对象类型,满足了java一切皆是对象的思想
什么是SpringMVC
一,首先是一个MVC框架。
在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错。还是为了组内开发人员之间的配合。总之就是一种分层工作的办法。
二,springMVC,是spring的一个子框架,当然拥有spring的特性,如依赖注入。
三,springMVC的信息流是什么样的?
首先用户通过HTTP请求到服务器,服务器会根据你的url来将请求转到不同的控制器Controller。这是第一步,具体需要做的是在web.xml中设置URLpattern映射到spring的DispatcherServlet,这是控制器是负责第一道处理,用来转发请求的,它会将请求转发到合适的Controller上。那么问题来了,它是根据什么转发呢?这个问题有些混乱,原因是springMVC一直在升级,不断贡献新的url到Controller的映射方法。但是万变不离其宗,不管如何变,它的目的都不变,就是设法建立url到Controller的映射,找到这个目的之后,看起来就容易一些。具体来看,
方法1,在springmvc的配置文件中,直接将bean的name写成一个url,如
<bean name="/product_input" class="com.ap.ProductInputController" />
通过这句配置,就直接将/product_input这url的请求转发到了ProductInputController这个类上。
注:但是这个方法被认为是老套的方法,现在已经不流行了。了解就可以,现在推荐的是注解的方式,即方法2的方式。
方法2,这种方式,在给Controller命名时,就可以无所谓了, 它的映射不是依赖这个名字,所以可以像下面这种方式来写这个bean的配置,可以随便起一个,如
<bean name=”product” class="com".ap.ProductInputController />
到这里,显然还是没有实现url到Controller的映射,因为url都还没看见呢,
现在的springMVC有一个注解是RequestMapping,专门负责映射url的,比方说需要映射到ProductInputController的 addProduct()这个方法,只需要在这个方法上加上一个注解,如
@RequestMapping(name=”product_input”)
addProduct()
通过这个注解,就可以将product_input这个url映射到addProduct这个方法了。是不是很简单。其实做的事情都一样,只不过是换了一种写法和位置。
感觉好神奇的样子,我一开始也有这种感觉,直到我了解了原始Servlet是如何将url和处理业务的类联系起来的,才发现这个过程也没有那么神秘,这里推荐一本书《SpringMVC学习指南》 Paul Deck著,适合0基础的人看,例子很详细。
我大概说一下url到Controller是怎么回事:
起点是,用户通过HTTP请求了服务器,那么一定就有URL,比方说是http://www.dudu.com/getName,其中getName就是我的url,假设你的servlet是部署在tomcat中的,在web.xml这个配置文件中,应该有url到某个类的关系,或者通过别的注解的方法 如@Webservlet(name= “xxController”, urlPatterns = {“product_input”}), 这里意思就是这个url进来后,把请求交给xxController这个class去处理,这个类继承了HttpServlet, 并且重写的doGet方法,你的请求就会来到这个方法里,然后,在方法内调用request.getRequestURI这个方法,拿到了你的url=getName,之后就是字符串匹配equals,调用后面具体的类。
我们使用框架的原因,就是在开发中,这样的步骤都是重复的,而且每次都一样,所以写框架的人,就把这样套路式的代码封装了, 细节都交给他来处理,我们只要做两件和自己业务相关的事,一个是确定url,二是,这个url指向那个类。写到这里基本把url到Controller这件事说完了。这里有两个类一个是DispatcherServlet,这个是SpringMVC框架自带的,一个就是你自己处理业务的类,比如是ProductController。控制器的命名都喜欢叫XXXController。下面画一张图说明这一步
四,MVC,先说的居然是C,Controller,下面说View,就是视图,展示。用户的浏览器,看到的都是比较美观的网页,这就是HTML,它负责来将苦涩的数据,展现成各种样式,让普通用户看起来也不错,而不是一堆JSON数据。用户的请求进来之后,肯定还是要返回给用户页面的,这每个页面就是一个VIEW,view就像一个网页的框架,某个页面的框架是固定的,不同的是其中的数据。比方说购物车页面,就是一个框架。那你的购物车和我的大体看起来是一样的,但其中的具体内容不同,因为买的商品不同,而这具体的东西,或叫做数据,就是Model。现在M和V就有了。
下面再串一个这个流程,刚才说到请求已经到了Controller,这个类的作用就是1,选择适当的view返回给用户,2,组织数据,即生成Model。网络传输和信息技术主要处理的就是数据,而现在数据就放在Model中,或者把放数据的地方叫做Model,比如用户在请求查询用户信息,那么Controller做的就是,在数据库中找到这些信息,然后把信息添加到Model中,然后把Model和对应的View一起返回给DispatcherServlet。 这里继续补充上一张图:
五,现在DispatcherServlet已经拿到Model里的数据和该用哪个View来展示给用户了。
所以会将Model和View融合,具体就是用Model的数据把View的变量都换成具体的值,然后view就变成一个HTML的页面了,最后把这个HTML返回给用户,用户那边用浏览器来解释HTML,看到就是正常的网页。 全过程结束。
spring的优点
1、非侵入式设计
Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
2、方便解耦、简化开发
Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器的管理,大大的降低了组件之间的耦合性。
3、支持AOP
Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事物、日志等进行集中式处理,从而提高了程序的复用性。
4、支持声明式事务处理
只需要通过配置就可以完成对事物的管理,而无须手动编程。
5、方便程序的测试
Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。
6、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。
7、降低Jave EE API的使用难度。
Spring对Java EE开发中非常难用的一些API(如JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
spring项目中启动的注解是什么?
1.@ComponentScan注解,spring context包下,可以理解嘛,扫描srping bean放在ioc容器中的。
ApplicationContext是接口,就是IOC容器嘛,也在这个包下。spring-context.jar包下。
如:
@ComponentScan(basePackages = "com.pingan.property.icore.pap.*")
2.@Configuration注解,也在spring-context.jar包下。用于注册bean到ioc容器中,@Configuration注解里面必须包含@Bean注解。
org.springframework.context.annotation.Configuration
同样,@configure是将bean注册到ioc容器中的,当然也都要在spring-context.jar包下了
多表查询有几种方式?
使用sql语句实现多表查询,比较常用的有inner join,left join,right join,full join,union几种方式。下面介绍这几种多表查询的方法。
方法/步骤
-
1
在数据库新建一张Persons数据表,数据表内有五个字段,三条记录。
-
2
在数据库新建一张Orders数据表,数据表内有三个字段,五条记录,其中Id_P字段是连接Persons表的标记。
-
3
多表inner join内连接方式,在多表查询中,只要存在至少一个匹配时,就返回行数据。例如,查询Persons表数据,同时连接Orders表一起查询,结果如下:
-
4
多表left join左连接方式,在多表查询中,从左表返回所有的行,如果右表有匹配的行数据就一起返回,如果没有匹配的数据,只返回左表的数据。例子如下:
![sql多表连接查询中有几种连接方式]
-
5
多表right join右连接方式,在多表查询中,查询的数据会先从右表中返回所有的行,如果左表存在匹配的行,则一起返回,如果左表不存在匹配的行,则只返回右表匹配的行。例子如下:
![sql多表连接查询中有几种连接方式]
-
6
多表full join查询方式,在多表查询中,只要多表中某个表存在匹配的行,就返回行数据。例子如下:
![sql多表连接查询中有几种连接方式]
-
7
多表union查询方式,主要是将多张表的select语句获得的结果集合并在一起。例如,存在两张表,一张Employees_China表,一张Employees_USA表,将两张表的数据合并在一起。
![sql多表连接查询中有几种连接方式]
MySQL数据库分组查询
在 MySQL 中,GROUP BY 关键字可以根据一个或多个字段对查询结果进行分组。
使用 GROUP BY 关键字的语法格式如下:
GROUP BY <字段名>
其中,“字段名”表示需要分组的字段名称,多个字段时用逗号隔开。
GROUP BY单独使用
单独使用 GROUP BY 关键字时,查询结果会只显示每个分组的第一条记录。
例 1
下面根据 tb_students_info 表中的 sex 字段进行分组查询,SQL 语句和运行结果如下:
mysql> SELECT `name`,`sex` FROM tb_students_info
-> GROUP BY sex;
+-------+------+
| name | sex |
+-------+------+
| Henry | 女 |
| Dany | 男 |
+-------+------+
2 rows in set (0.01 sec)
结果中只显示了两条记录,这两条记录的 sex 字段的值分别为“女”和“男”。
GROUP BY 与 GROUP_CONCAT()
GROUP BY 关键字可以和 GROUP_CONCAT() 函数一起使用。GROUP_CONCAT() 函数会把每个分组的字段值都显示出来。
例 2
下面根据 tb_students_info 表中的 sex 字段进行分组查询,使用 GROUP_CONCAT() 函数将每个分组的 name 字段的值都显示出来。SQL 语句和运行结果如下:
mysql> SELECT `sex`, GROUP_CONCAT(name) FROM tb_students_info
-> GROUP BY sex;
+------+----------------------------+
| sex | GROUP_CONCAT(name) |
+------+----------------------------+
| 女 | Henry,Jim,John,Thomas,Tom |
| 男 | Dany,Green,Jane,Lily,Susan |
+------+----------------------------+
2 rows in set (0.00 sec)
由结果可以看到,查询结果分为两组,sex 字段值为“女”的是一组,值为“男”的是一组,且每组的学生姓名都显示出来了。
例 3
下面根据 tb_students_info 表中的 age 和 sex 字段进行分组查询。SQL 语句和运行结果如下:
mysql> SELECT age,sex,GROUP_CONCAT(name) FROM tb_students_info
-> GROUP BY age,sex;
+------+------+--------------------+
| age | sex | GROUP_CONCAT(name) |
+------+------+--------------------+
| 21 | 女 | John |
| 22 | 女 | Thomas |
| 22 | 男 | Jane,Lily |
| 23 | 女 | Henry,Tom |
| 23 | 男 | Green,Susan |
| 24 | 女 | Jim |
| 25 | 男 | Dany |
+------+------+--------------------+
7 rows in set (0.00 sec)
上面实例在分组过程中,先按照 age 字段进行分组,当 age 字段值相等时,再把 age 字段值相等的记录按照 sex 字段进行分组。
多个字段分组查询时,会先按照第一个字段进行分组。如果第一个字段中有相同的值,MySQL 才会按照第二个字段进行分组。如果第一个字段中的数据都是唯一的,那么 MySQL 将不再对第二个字段进行分组。
GROUP BY 与聚合函数
在数据统计时,GROUP BY 关键字经常和聚合函数一起使用。
聚合函数包括 COUNT(),SUM(),AVG(),MAX() 和 MIN()。其中,COUNT() 用来统计记录的条数;SUM() 用来计算字段值的总和;AVG() 用来计算字段值的平均值;MAX() 用来查询字段的最大值;MIN() 用来查询字段的最小值。
关于聚合函数的详细内容可以阅读学习《》一节。
例 4
下面根据 tb_students_info 表的 sex 字段进行分组查询,使用 COUNT() 函数计算每一组的记录数。SQL 语句和运行结果如下:
mysql> SELECT sex,COUNT(sex) FROM tb_students_info
-> GROUP BY sex;
+------+------------+
| sex | COUNT(sex) |
+------+------------+
| 女 | 5 |
| 男 | 5 |
+------+------------+
2 rows in set (0.00 sec)
结果显示,sex 字段值为“女”的记录是一组,有 5 条记录;sex 字段值为“男”的记录是一组,有 5 条记录。
GROUP BY 与 WITH ROLLUP
WITH POLLUP 关键字用来在所有记录的最后加上一条记录,这条记录是上面所有记录的总和,即统计记录数量。
例 5
下面根据 tb_students_info 表中的 sex 字段进行分组查询,并使用 WITH ROLLUP 显示记录的总和。
mysql> SELECT sex,GROUP_CONCAT(name) FROM tb_students_info
->GROUP BY sex WITH ROLLUP;
+------+------------------------------------------------------+
| sex | GROUP_CONCAT(name) |
+------+------------------------------------------------------+
| 女 | Henry,Jim,John,Thomas,Tom |
| 男 | Dany,Green,Jane,Lily,Susan |
| NULL | Henry,Jim,John,Thomas,Tom,Dany,Green,Jane,Lily,Susan |
+------+------------------------------------------------------+
3 rows in set (0.00 sec)