1.MyBatis中的事务是怎样操作的
MP
@Transactional(rollbackFor = Exception.class )
// spring事务控制 @Transactional 通过环绕通知控制 around
// around 特征 业务执行前(开启事务控制),执行目标方法 ,业务执行后(成功提交事务 失败回滚事务)
/**
* rollbackFor = Exception.class, 遇到异常回滚数据
* noRollbackFor = Exception.class 遇到异常不回滚数据
* spring 默认事务策略
* 1.如果控制的方法出现了运行时异常,则事务自动的回滚
* 2.如果控制的方法出现了编译时异常, 则事务不会自动回滚,
* spring任务程序既然出现提示需要异常处理,则默认由程序员自己处理,spring不控制
* IOC底层 反射,工厂设计模式
* DI底层
* AOP底层 around 动态代理
<insert useGeneratedKeys="true" keyProperty="id" keyColumn="id"></insert>-->主键回显
Mybatis
(a):使用JDBC的事务管理机制:即使用java.Sql.Connection对象完成对事务的提交,回滚和关闭操作。
(b):使用MANAGED的事务管理机制:mybatis本身不会去实现事务管理的相关操作,而是交个外部容器来管理事务。当与spring整合使用后,一般使用spring来管理事务。
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
2.#{}和${}的区别
#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
Mybatis在处理时 , 是 原 值 传 入 , 就 是 把 {}时,是原值传入,就是把时,是原值传入,就是把{}替换成变量的值,相当于JDBC中的Statement编译
变量替换后,#{} 对应的变量自动加上单引号 ‘’;变量替换后,${} 对应的变量不会加上单引号 ‘’
#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入
#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外
Mybatis都有哪些Executor执行器?它们之间的区别是什么?
Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。
BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
2.Maven工具打包是怎样打包的(命令打包方式),你知道Maven命令不?
1.打包,包含进行单元测试
mvn install
2.打包,跳过单元测试
mvn install -Dmaven.test.skip
3.生成source
mvn source:jar
4.生成jar和souce.jar
mvn clean install source:jar -Dmaven.test.skip
clear清除编译文件 install下载安装jar包 jar package打包(编译-试运行-打包)
test命令,可在命令提示符界面运行maven项目中测试类中的测试方法,即执行那些带有@Test注解的测试方法。
1、只会执行Maven项目中src/test/java目录下的测试类。
2、只有类的命名规范满足XxxTest.java才会执行。
3.Git或SVN版本控制命令知道多少?
SVN
svn status 查看状态 st
svn add name 添加到仓库
svn commit -m “注释" 简:ci
svn updata //先更新所有数据
svn log //打印所有版本
svn remove name 移除文件
简:rm
GIT
回滚到某次提交。索引和工作空间的内容是不变的。如果想再次提交,直接commit即可
git reset - -soft commitId
回滚到某次提交(git reset默认的模式)。索引的内容会改变,工作空间的内容不变。如果想再次提交,需要先add,再commit
git reset - - mixed commitId
回滚到某次提交。索引和工作空间的内容都会变成给定提交时的状态,也就是在给定提交后修改的内容都会丢失,所以需要特别注意
git reset - - hard commitId
列出所有本地分支(前面有星号“*”的为当前工作分支)
git branch
查看提交历史
git log
列出所有远程分支
git branch -r
列出所有本地和远程分支
git branch -a
创建名为“name”的新分支
git branch [name]
切换到“name”分支
git checkout [name]
创建名为“name”的新分支,并切换到该分支
git checkout -b [name]
删除名为“name”的分支
git branch -d [name]
将“name”分支合并到当前分支
git merge [name]
4.Spring的业务流程?
1.首先解析 spring.xml 配置文件,把其中 <bean> 解析为 BeanDefinition, 存入beanFactory
<bean id="" class="" init-method="" destroy-method="" scope="" lazy-init="">
2.把 BeanDefinition 中的定义读取到一个map集合中管理起来了,但还没有创建 bean 的单例对象
执行beanFactory的后处理器
3.接下来 由 beanFactory 创建每个类对应的单例对象, 利用了反射根据类名创建每个类的实例对象(构造,初始化方法)
4.执行 bean 的后处理器, 它其中有两个方法,会在 bean 的初始化方法前后被调用
会把这些结果 存入 beanFactory 的 singletonObjects 这样一个map集合里
userService -> userService对象
5.执行依赖注入
主要为了解决循环引用问题
class A {
@Autowired
private B b;
}
class B {
@Autowired
private A a;
}
key value
a new A();
b new B();
map.get(“a”).setB( map.get(“b”) );
map.get(“b”).setA( map.get(“a”) )
容器.getBean(“bean id”) 根据bean 的id,把bean id当做key,进入 singletonObjects 获取值
返回的结果就是 userSerivce对象
5.SpringAop是什么
面向切面编程
1.前置通知(Before Advice): 在连接点之前执行的Advice,不过除非它抛出异常,否则没有能力中断执行流。使用 @Before 注解使用这个Advice。
2.返回之后通知(After Retuning Advice): 在连接点正常结束之后执行的Advice。例如,如果一个方法没有抛出异常正常返回。通过 @AfterReturning 关注使用它。
3.抛出(异常)后执行通知(After Throwing Advice): 如果一个方法通过抛出异常来退出的话,这个Advice就会被执行。通用 @AfterThrowing 注解来使用。
4.后置通知(After Advice): 无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会执行在结束后执行这些Advice。通过 @After 注解使用。
5.围绕通知(Around Advice): 围绕连接点执行的Advice,就你一个方法调用。这是最强大的Advice。通过 @Around 注解使用。
Spring AOP 代理是什么?
代理是使用非常广泛的设计模式。简单来说,代理是一个看其他像另一个对象的对象,但它添加了一些特殊的功能。
Spring AOP是基于代理实现的。AOP 代理是一个由 AOP 框架创建的用于在运行时实现切面协议的对象。
Spring AOP默认为 AOP 代理使用标准的 JDK 动态代理。这使得任何接口(或者接口的集合)可以被代理。Spring AOP 也可以使用 CGLIB 代理。这对代理类而不是接口是必须的。
如果业务对象没有实现任何接口那么默认使用CGLIB。
6.冒泡排序、阶乘
冒泡
int i, j, temp;
for (j = 0; j < len - 1; j++)
{
for (i = 0; i < len - 1 - j; i++)
if (a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
选择排序:
int array[] = { 7,10,12,3,9,5 };
for (int i = 0; i < 6; i++)
{
int minkey = array[i];
for (int j = i + 1; j < 6; j++)
{
if (minkey < array[j])
{
int tamp = array[j];
array[j] = minkey;
minkey = tamp;
}
}
array[i] = minkey;
}
阶乘:
public class RecursionTest{
public static void main(String[] args){
int num = getValue(5);
System.out.println(num);
}
public static int getValue(int num){
if(num < 0 || num == 0 || num == 1){
return 1;
}else{
num = num*getValue(num - 1);
}
return num;
}
}
public Class RepeatTest{
public static void main(String[] args){
int num = getValue(5);
System.out.println(num);
}
public static int getValue(int num){
int sum = 1;
for(i = 0,i <= num,i++){
sum*=i;
}
return sum;
}
}
7.你是怎样看待线程安全的问题的
1.多线程环境
2.多个线程要有共享数据
3.多个线程对共享数据进行修改
8.Redis的储存过程(来为大佬解释解释)
9.Redis是怎么实现高可用的
●数据持久化
●主从数据同步(主从复制)
●Redis 哨兵模式(Sentinel)
●Redis 集群(Cluster)
其中数据持久化保证了系统在发生宕机或者重启之后数据不会丢失,增加了系统的可靠性和减少了系统不可用的时间(省去了手动恢复数据的过程);而主从数据同步可以将数据存储至多台服务器,这样当遇到一台服务器宕机之后,可以很快地切换至另一台服务器以继续提供服务;哨兵模式用于发生故障之后自动切换服务器;而 Redis 集群提供了多主多从的 Redis 分布式集群环境,用于提供性能更好的 Redis 服务,并且它自身拥有故障自动切换的能力。
10.Nginx怎样实现反向代理的
Nginx的2种用途
静态内容的web服务器;
反向代理服务器;
反向代理服务器决定哪台服务器提供服务。返回代理服务器不提供服务器。只是请求的转发。
接收用户请求是异步的,即先将用户请求全部接收下来,再一次性发送后后端web服务器,极大的减轻后端web服务器的压力;
nginx代理和后端web服务器间无需长连接;
发送响应报文时,是边接收来自后端web服务器的数据,边发送给客户端的;
11.Java中的数据类型
12.基本数据类型都有什么
8种基本类型 数组,对象
13.Mybatis怎样操作数据库的
配置--mybatis-config.xml 是mybatis的核心配置文件,用来配置事务,数据库的连接信息
--UserMapper.xml 是用来存储操作User表的大量的SQL
--SqlSessionFactory 是会话工厂,创建会话
--SqlSession 是会话,用来执行SQL(select()/insert()....)
--加载核心配置文件mybatis-config.xml
--创建会话工厂
--创建会话
--执行SQL
--处理返回值
package cn.tedu.mybatis;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
//测试 mybatis
public class TestMybatis {
public static void main(String[] args) throws IOException {
// 加载核心配置文件mybatis-config.xml
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 创建会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 创建会话
SqlSession session = factory.openSession();
// 执行SQL
// session.selectList(namespace的值.sql的id);
List<User> list = session.selectList("userMapperNS.getAll");
// 处理返回值
for (User u : list) {
System.out.println(u);
}
}
}
14.Linux命令关键字
15.SpringBoot和SSM的区别
16.SpringBoot和SpringCloud的区别
17.SQL语句关键字 update insert select delete alter table database rename drop group by having limit
18.你用过那些数据库
mysql mariadb oracle
20.说一下SpringMVC
21.Spring中的注解有什么
@Component 标注一个普通的spring bean类;
@Service 在业务逻辑层使用(service层)
@Repository 在数据访问层使用(dao层)
@Controller 在展现层使用,控制器的声明(C)
@Autowired : 自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。可以作用在变量或者方法上
@Resource : 直接按照bean的id注入,可以独立使用。
@Value : 用于注入基本类型和String类型的数据。
22.Shiro框架的权限控制是怎样实现的(一般会说一个情景)
Shiro是Apache 旗下的一个简单易用的权限框架,可以轻松的完成 认证、授权、加密、会话管理、与 Web 集成、缓存等
24.前端的问题也会问到,有的会问的比较深,比如用JavaScript实现一个页面
25.设计模式大概能说两三种就行
//饿汉式
//思考:饿汉式会不会出现线程安全问题?不会产生线程安全问题
public class Cat {
private static Cat cat = new Cat();
private Cat(){}
public static Cat getCat(){
return cat;
}
}
//懒汉式
//思考:懒汉式会不会产生线程安全问题?
//如果会产生,请模拟出来
public class Bird {
private static Bird bird = null;
private Bird(){}
public static Bird getBird(){
if(bird == null) {
bird = new Bird();
}
return bird;
}
}
public class MyThread12 extends Thread{
public void run() {
Bird bird = Bird.getBird();
System.out.println(bird);
}
}
public class MyThread13 extends Thread{
public void run() {
Bird bird = Bird.getBird();
System.out.println(bird);
}
}
public class TestMyThread12 {
public static void main(String[] args) {
MyThread12 mt12 = new MyThread12();
MyThread13 mt13 = new MyThread13();
mt12.start();
mt13.start();
}
}
26.你见过什么异常
27.Synchronized的用法
一 修饰方法
Synchronized修饰一个方法很简单,就是在方法的前面加synchronized,synchronized修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。
二 修饰一个代码块
1)一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞
三 修饰一个静态的方法
Synchronized也可修饰一个静态方法,静态方法是属于类的而不属于对象的。同样的,synchronized修饰的静态方法锁定的是这个类的所有对象。
四 修饰一个类
Synchronized还可作用于一个类,用法如下:
class ClassName {
public void method() {
synchronized(ClassName.class) {
// todo
}
}
}
/**
* 同步线程
*/
class SyncThread implements Runnable {
private static int count;
public SyncThread() {
count = 0;
}
public static void method() {
synchronized(SyncThread.class) {
for (int i = 0; i < 5; i ++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++));
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void run() {
method();
}
方式一:使用同步代码块
语法格式: synchronized(锁对象){
需要锁住的代码
}
锁对象可以是任意对象
//模拟售票
public class SaleTicket extends Thread {
//有100张票
private static int ticket = 100;
//创建锁对象
private static Object o = new Object();
public void run() {
synchronized (o) {
while(ticket > 0) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "卖除了1张票,还剩下" + (--ticket) + "张票");
}
}
}
}
public class TestSaleTicket {
public static void main(String[] args) {
SaleTicket s1 = new SaleTicket();
s1.setName("火车站");
SaleTicket s2 = new SaleTicket();
s2.setName("代售点");
SaleTicket s3 = new SaleTicket();
s3.setName("网络");
s1.start();
s2.start();
s3.start();
}
}
28.你知道的map, 怎样遍历map
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
public class Test4 {
public static void main(String[] args) {
HashMap<Phone,String> map = new HashMap<>();
map.put(new Phone("Apple",7000),"美国");
map.put(new Phone("Sony",5000),"日本");
map.put(new Phone("Huawei",6000),"中国");
Set<Phone> phones = map.keySet();
Iterator<Phone> iterator = phones.iterator();//迭代器
while (iterator.hasNext()){
Phone next = iterator.next();
System.out.println(next.getBrand()+"=="+next.getPrice()+"=="+map.get(next));
}
}
}
public class Test4 {
public static void main(String[] args) {
HashMap<Phone,String> map = new HashMap<>();
map.put(new Phone("Apple",7000),"美国");
map.put(new Phone("Sony",5000),"日本");
map.put(new Phone("Huawei",6000),"中国");
Set<Map.Entry<Phone, String>> entries = map.entrySet();//增强for循环
for (Map.Entry<Phone, String> entry : entries) {
System.out.println(entry.getKey().getBrand()+"==="+entry.getKey().getPrice()+"==="+entry.getValue());
}
}
}
29.JVM内部图结构图画出来
第一,JVM分为五个区域:虚拟机栈、本地方法栈、方法区、堆、程序计数器。PS:大家不要排斥英语,此处用英文记忆反而更容易理解。
第二,JVM五个区中虚拟机栈、本地方法栈、程序计数器为线程私有,方法区和堆为线程共享区。图中已经用颜色区分,绿色表示“通行”,橘黄色表示停一停(需等待)。
第三,JVM不同区域的占用内存大小不同,一般情况下堆最大,程序计数器较小。那么最大的区域会放什么?当然就是Java中最多的“对象”了。
30.ArrayList和LinkinList的区别