diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..173454b --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Created by .ignore support plugin (hsz.mobi) +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen diff --git "a/.idea/Java\351\253\230\347\272\247\345\267\245\347\250\213\345\270\210.iml" "b/.idea/Java\351\253\230\347\272\247\345\267\245\347\250\213\345\270\210.iml" deleted file mode 100644 index d6ebd48..0000000 --- "a/.idea/Java\351\253\230\347\272\247\345\267\245\347\250\213\345\270\210.iml" +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 975ddc1..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 9f8e949..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index d7b8649..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,621 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + 1615231026652 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/IPersistence_test/IPersistence_test.iml b/MybatisLearning/IPersistence_test/IPersistence_test.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/MybatisLearning/IPersistence_test/IPersistence_test.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/MybatisLearning/IPersistence_test/pom.xml b/MybatisLearning/IPersistence_test/pom.xml new file mode 100644 index 0000000..0e31efc --- /dev/null +++ b/MybatisLearning/IPersistence_test/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + com.lagou + IPersistence_test + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/MybatisLearning/IPersistence_test/src/main/resources/UserMapper.xml b/MybatisLearning/IPersistence_test/src/main/resources/UserMapper.xml new file mode 100644 index 0000000..69e9edf --- /dev/null +++ b/MybatisLearning/IPersistence_test/src/main/resources/UserMapper.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/IPersistence_test/src/main/resources/sqlMapConfig.xml b/MybatisLearning/IPersistence_test/src/main/resources/sqlMapConfig.xml new file mode 100644 index 0000000..08d201f --- /dev/null +++ b/MybatisLearning/IPersistence_test/src/main/resources/sqlMapConfig.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/MybatisLearning.iml b/MybatisLearning/MybatisLearning.iml new file mode 100644 index 0000000..8d8ffd9 --- /dev/null +++ b/MybatisLearning/MybatisLearning.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/compiler.xml b/MybatisLearning/http_test/.idea/compiler.xml new file mode 100644 index 0000000..b1ee830 --- /dev/null +++ b/MybatisLearning/http_test/.idea/compiler.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/encodings.xml b/MybatisLearning/http_test/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/MybatisLearning/http_test/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/inspectionProfiles/Project_Default.xml b/MybatisLearning/http_test/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6560a98 --- /dev/null +++ b/MybatisLearning/http_test/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/misc.xml b/MybatisLearning/http_test/.idea/misc.xml new file mode 100644 index 0000000..4b661a5 --- /dev/null +++ b/MybatisLearning/http_test/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/uiDesigner.xml b/MybatisLearning/http_test/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/MybatisLearning/http_test/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/.idea/workspace.xml b/MybatisLearning/http_test/.idea/workspace.xml new file mode 100644 index 0000000..be15435 --- /dev/null +++ b/MybatisLearning/http_test/.idea/workspace.xml @@ -0,0 +1,503 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1615448075795 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No facets are configured + + + + + + + + + + + + + + + 1.8 + + + + + + + + http_test + + + + + + + + 1.8 + + + + + + + + Maven: com.squareup.okhttp3:okhttp:3.6.0 + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/http_test.iml b/MybatisLearning/http_test/http_test.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/MybatisLearning/http_test/http_test.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/MybatisLearning/http_test/pom.xml b/MybatisLearning/http_test/pom.xml new file mode 100644 index 0000000..a5b74bb --- /dev/null +++ b/MybatisLearning/http_test/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + com.cdmone + http_test + 1.0-SNAPSHOT + + + + + com.squareup.okhttp3 + okhttp + 3.6.0 + + + joda-time + joda-time + 2.9.9 + + + junit + junit + 4.12 + test + + + + org.springframework.boot + spring-boot-starter + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + + com.google.code.gson + gson + 2.6.2 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/http_test/src/main/java/AlertInfo.java b/MybatisLearning/http_test/src/main/java/AlertInfo.java new file mode 100644 index 0000000..69c50da --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/AlertInfo.java @@ -0,0 +1,145 @@ +import java.io.Serializable; + +public class AlertInfo implements Serializable { + private String manufacturerServerId; + private String alertId; + private String alertLevel; + private String dataCenterName; + private String networkZone; + private String internetProtocol; + private String alertSource; + private String alertType; + private String alertObject; + private String alertContent; + private String alertTime; + private String alertCatalog; + + @Override + public String toString() { + return "AlertInfo{" + + "manufacturerServerId='" + manufacturerServerId + '\'' + + ", alertId='" + alertId + '\'' + + ", alertLevel='" + alertLevel + '\'' + + ", dataCenterName='" + dataCenterName + '\'' + + ", networkZone='" + networkZone + '\'' + + ", internetProtocol='" + internetProtocol + '\'' + + ", alertSource='" + alertSource + '\'' + + ", alertType='" + alertType + '\'' + + ", alertObject='" + alertObject + '\'' + + ", alertContent='" + alertContent + '\'' + + ", alertTime='" + alertTime + '\'' + + ", alertCatalog='" + alertCatalog + '\'' + + '}'; + } + + public AlertInfo(String manufacturerServerId, String alertId, String alertLevel, String dataCenterName, String networkZone, String internetProtocol, String alertSource, String alertType, String alertObject, String alertContent, String alertTime, String alertCatalog) { + this.manufacturerServerId = manufacturerServerId; + this.alertId = alertId; + this.alertLevel = alertLevel; + this.dataCenterName = dataCenterName; + this.networkZone = networkZone; + this.internetProtocol = internetProtocol; + this.alertSource = alertSource; + this.alertType = alertType; + this.alertObject = alertObject; + this.alertContent = alertContent; + this.alertTime = alertTime; + this.alertCatalog = alertCatalog; + } + + public String getManufacturerServerId() { + return manufacturerServerId; + } + + public void setManufacturerServerId(String manufacturerServerId) { + this.manufacturerServerId = manufacturerServerId; + } + + public String getAlertId() { + return alertId; + } + + public void setAlertId(String alertId) { + this.alertId = alertId; + } + + public String getAlertLevel() { + return alertLevel; + } + + public void setAlertLevel(String alertLevel) { + this.alertLevel = alertLevel; + } + + public String getDataCenterName() { + return dataCenterName; + } + + public void setDataCenterName(String dataCenterName) { + this.dataCenterName = dataCenterName; + } + + public String getNetworkZone() { + return networkZone; + } + + public void setNetworkZone(String networkZone) { + this.networkZone = networkZone; + } + + public String getInternetProtocol() { + return internetProtocol; + } + + public void setInternetProtocol(String internetProtocol) { + this.internetProtocol = internetProtocol; + } + + public String getAlertSource() { + return alertSource; + } + + public void setAlertSource(String alertSource) { + this.alertSource = alertSource; + } + + public String getAlertType() { + return alertType; + } + + public void setAlertType(String alertType) { + this.alertType = alertType; + } + + public String getAlertObject() { + return alertObject; + } + + public void setAlertObject(String alertObject) { + this.alertObject = alertObject; + } + + public String getAlertContent() { + return alertContent; + } + + public void setAlertContent(String alertContent) { + this.alertContent = alertContent; + } + + public String getAlertTime() { + return alertTime; + } + + public void setAlertTime(String alertTime) { + this.alertTime = alertTime; + } + + public String getAlertCatalog() { + return alertCatalog; + } + + public void setAlertCatalog(String alertCatalog) { + this.alertCatalog = alertCatalog; + } +} diff --git a/MybatisLearning/http_test/src/main/java/DateUtils.java b/MybatisLearning/http_test/src/main/java/DateUtils.java new file mode 100644 index 0000000..54b8580 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/DateUtils.java @@ -0,0 +1,12 @@ + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +public class DateUtils { + public static String format(String patten){ + DateTimeFormatter fmt = DateTimeFormat.forPattern(patten); + String dateStr = fmt.print(DateTime.now().getMillis()); + return dateStr; + } +} diff --git a/MybatisLearning/http_test/src/main/java/HttpUtils.java b/MybatisLearning/http_test/src/main/java/HttpUtils.java new file mode 100644 index 0000000..c491921 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/HttpUtils.java @@ -0,0 +1,116 @@ + +import okhttp3.*; +import sun.net.www.http.HttpClient; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +public class HttpUtils { + + private static final String MEDIA_TYPE_JSON = "application/json;charset=utf-8"; + + private static String COMPANY_PREFIX = "ECLOUDTECHCOMCN"; + + + + //MEDIA_TYPE_TEXT post请求不是application/x-www-form-urlencoded的, + // 全部直接返回,不作处理,即不会解析表单数据来放到request parameter map中。 + // 所以通过request.getParameter(name)是获取不到的。只能使用最原始的方式,读取输入流来获取。 + private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"); + + + + /** + * @param url , json + * @return java.lang.String + * @descprition + * @version 1.0 post+json方式,token只有在校验用户token换取组户名时必填,其他场景不需要填写 + */ + public static String sendByPostJson(String url, String json,String token) { + String result; + if("".equals(token) || null == token){ + token = COMPANY_PREFIX+ DateUtils.format("yyyyMMddHHmmssSSS"); + }else { + token = "Bearer "+token; + } + System.out.println("send post request,url->"+url+" params->"+json+" token->"+token); + //log.info("send post request,url->{},params->{},token->{}",url,json,token); + //RequestBody body = RequestBody.create(null, new byte[]{}); + RequestBody body = RequestBody.create(MediaType.parse(MEDIA_TYPE_JSON),json); + Request request = new Request.Builder() + .addHeader("Authorization",token) + .addHeader("Content-Type",MEDIA_TYPE_JSON) + .url(url) + .post(body) + .build(); + Response response ; + try { + + /** + * 忽略https证书的OkHttpClient + * 新建一个OkHttpClient的单例模式 + */ + response = new OkHttpClient().newBuilder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + //.sslSocketFactory(SSLSocketClient.getSSLSocketFactory()) + .hostnameVerifier(SSLSocketClient.getHostnameVerifier()) + .build().newCall(request).execute(); + //response = client.newCall(request).execute(); + result = response.body().string(); + System.out.println("send post request,receive data->"+result); + response.close(); + //log.info("send post request,receive data->{}",result); + return result; + } catch (IOException e) { + //log.error("sendByPostJson error",e); + System.out.println("sendByPostJson error"+e); + return "kong"; + } + } + + +// public static String sendByPostTest(String url, String json,String token) { +// String result; +// //OkHttpClient client = new OkHttpClient(); +// +// if("".equals(token) || null == token){ +// token = COMPANY_PREFIX+ DateUtils.format("yyyyMMddHHmmssSSS"); +// }else { +// token = "Bearer "+token; +// } +// System.out.println("send post request,url->"+url+" params->"+json+" token->"+token); +// //log.info("send post request,url->{},params->{},token->{}",url,json,token); +// RequestBody body = RequestBody.create(MediaType.parse(MEDIA_TYPE_JSON), json); +// Request request = new Request.Builder() +// .addHeader("Authorization",token) +// .addHeader("Content-Type",MEDIA_TYPE_JSON) +// .addHeader("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4)") +// .addHeader("Accept-Language","zh-CN,zh;q=0.9") +// .url(url) +// .post(body) +// .build(); +// OkHttpClient.Builder builder = new OkHttpClient.Builder(); +// builder.connectTimeout(30, TimeUnit.SECONDS); +// builder.readTimeout(30, TimeUnit.SECONDS); +// builder.writeTimeout(30, TimeUnit.SECONDS); +// OkHttpClient client = builder.build(); +// Response response ; +// try { +// //response = OKHttpClientBuilder.buildOKHttpClient().connectTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS).build().newCall(request).execute(); +// response = client.newCall(request).execute(); +// result = response.body().string(); +// System.out.println("send post request,receive data->{}"+result); +// response.close(); +// //log.info("send post request,receive data->{}",result); +// return result; +// } catch (IOException e) { +// //log.error("sendByPostJson error",e); +// System.out.println("sendByPostJson error"+e); +// return "kong"; +// } +// } + + +} diff --git a/MybatisLearning/http_test/src/main/java/OKHttpClientBuilder.java b/MybatisLearning/http_test/src/main/java/OKHttpClientBuilder.java new file mode 100644 index 0000000..09f9680 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/OKHttpClientBuilder.java @@ -0,0 +1,60 @@ +import okhttp3.OkHttpClient; + +import javax.net.ssl.*; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +/** + * Author: areful + * Date: 2019/2/15 + */ +public class OKHttpClientBuilder { + + // 编码格式。发送编码格式统一用UTF-8 + private static final String ENCODING = "UTF-8"; + + // 设置连接超时时间,单位毫秒。 + private static final int CONNECT_TIMEOUT = 6000; + + // 请求获取数据的超时时间(即响应时间),单位毫秒。 + private static final int SOCKET_TIMEOUT = 10000; + public static OkHttpClient getUnsafeOkHttpClient() { + + try { + final TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + } + }; + + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.sslSocketFactory(sslSocketFactory); + + builder.hostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + + return builder.build(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } +} diff --git a/MybatisLearning/http_test/src/main/java/SSLSocketClient.java b/MybatisLearning/http_test/src/main/java/SSLSocketClient.java new file mode 100644 index 0000000..e210b43 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/SSLSocketClient.java @@ -0,0 +1,58 @@ +import javax.net.ssl.*; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; + +public class SSLSocketClient { + /** + * 管理证书和信任证书的 + * @return + */ + //获取这个SSLSocketFactory + public static SSLSocketFactory getSSLSocketFactory() { + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, getTrustManager(), new SecureRandom()); + return sslContext.getSocketFactory(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //获取TrustManager + private static TrustManager[] getTrustManager() { + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + }; + return trustAllCerts; + } + + + /** + * 配置一个HostnameVerifier来忽略host验证 + * @return + */ + public static HostnameVerifier getHostnameVerifier() { + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslSession) { + return true;//信任所有证书 + } + }; + return hostnameVerifier; + + } + +} diff --git a/MybatisLearning/http_test/src/main/java/StorageInfo.java b/MybatisLearning/http_test/src/main/java/StorageInfo.java new file mode 100644 index 0000000..cf96956 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/StorageInfo.java @@ -0,0 +1,85 @@ +public class StorageInfo { + private String manufacturerServerId; + private String tenantId; + private String tenantName; + private String dataCenterName; + private String networkZone; + private String protectionLevel; + private String securityType; + private Integer storageCapacity; + + + public StorageInfo(String manufacturerServerId, String tenantId, String tenantName, String dataCenterName, String networkZone, String protectionLevel, String securityType, Integer storageCapacity) { + this.manufacturerServerId = manufacturerServerId; + this.tenantId = tenantId; + this.tenantName = tenantName; + this.dataCenterName = dataCenterName; + this.networkZone = networkZone; + this.protectionLevel = protectionLevel; + this.securityType = securityType; + this.storageCapacity = storageCapacity; + } + + @Override + public String toString() { + return "StorageInfo{" + + "manufacturerServerId='" + manufacturerServerId + '\'' + + ", tenantId='" + tenantId + '\'' + + ", tenantName='" + tenantName + '\'' + + ", dataCenterName='" + dataCenterName + '\'' + + ", protectionLevel='" + protectionLevel + '\'' + + ", securityType='" + securityType + '\'' + + ", storageCapacity='" + storageCapacity + '\'' + + '}'; + } + + public String getManufacturerServerId() { + return manufacturerServerId; + } + + public void setManufacturerServerId(String manufacturerServerId) { + this.manufacturerServerId = manufacturerServerId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + public String getDataCenterName() { + return dataCenterName; + } + + public void setDataCenterName(String dataCenterName) { + this.dataCenterName = dataCenterName; + } + + public String getProtectionLevel() { + return protectionLevel; + } + + public void setProtectionLevel(String protectionLevel) { + this.protectionLevel = protectionLevel; + } + + public String getSecurityType() { + return securityType; + } + + public void setSecurityType(String securityType) { + this.securityType = securityType; + } + + +} diff --git a/MybatisLearning/http_test/src/main/java/Test.java b/MybatisLearning/http_test/src/main/java/Test.java new file mode 100644 index 0000000..1632229 --- /dev/null +++ b/MybatisLearning/http_test/src/main/java/Test.java @@ -0,0 +1,37 @@ +import com.google.gson.Gson; + +public class Test { + + public static void main(String[] are){ + String url = "https://yxdint.tongdao.tech:21443/backup/uaa/current"; + String json = ""; + String alertUrl = "https://yxdint.tongdao.tech:21443/backup/logic/driving/v1/tenant/storage/consumption/info"; + String token = ""; + StorageInfo storageInfo = new StorageInfo("792167268883628035","1234","zaibei","DONG_CHONG","GOVERNMENT_EXTRANET","LOCAL","PLAIN",1234567); + HttpUtils.sendByPostJson(alertUrl,new Gson().toJson(storageInfo),token); + } + + + public void test2(){ + String url = "https://yxdint.tongdao.tech:21443/backup/uaa/current"; + String json = ""; + String alertUrl = "https://yxdint.tongdao.tech:21443/backup/logic/driving/v1/alert/info"; + String token = ""; + AlertInfo alertInfo = new AlertInfo("792167268883628035","123","SERIOUS", + "DONG_CHONG","GOVERNMENT_EXTRANET","123.123.123.123","zaibei2" + ,"备份","备份主机","备份作业10.24.68.02_D执行失败","20201231160800123","EVENT"); + String result = HttpUtils.sendByPostJson(alertUrl,json,token); + System.out.println(result); + } + + public void test3(){//{"message":"成功","status":0,"content":{"id":"1615580712136"}} + String url = "https://yxdint.tongdao.tech:21443/backup/uaa/current"; + String json = ""; + String alertUrl = "https://yxdint.tongdao.tech:21443/backup/logic/driving/v1/tenant/storage/consumption/info"; + String token = ""; + StorageInfo storageInfo = new StorageInfo("792167268883628035","1234","zaibei","DONG_CHONG","GOVERNMENT_EXTRANET","LOCAL","PLAIN",1234567); + HttpUtils.sendByPostJson(alertUrl,new Gson().toJson(storageInfo),token); + } + + +} diff --git "a/JavaSE/JavaSE(\344\270\211).md" b/MybatisLearning/http_test/src/main/resources/application.properties similarity index 100% rename from "JavaSE/JavaSE(\344\270\211).md" rename to MybatisLearning/http_test/src/main/resources/application.properties diff --git a/MybatisLearning/http_test/target/classes/AlertInfo.class b/MybatisLearning/http_test/target/classes/AlertInfo.class new file mode 100644 index 0000000..b1e3c9e Binary files /dev/null and b/MybatisLearning/http_test/target/classes/AlertInfo.class differ diff --git a/MybatisLearning/http_test/target/classes/DateUtils.class b/MybatisLearning/http_test/target/classes/DateUtils.class new file mode 100644 index 0000000..776f77f Binary files /dev/null and b/MybatisLearning/http_test/target/classes/DateUtils.class differ diff --git a/MybatisLearning/http_test/target/classes/HttpUtils.class b/MybatisLearning/http_test/target/classes/HttpUtils.class new file mode 100644 index 0000000..a4b0990 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/HttpUtils.class differ diff --git a/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$1.class b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$1.class new file mode 100644 index 0000000..d26e00c Binary files /dev/null and b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$1.class differ diff --git a/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$2.class b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$2.class new file mode 100644 index 0000000..7fdea40 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder$2.class differ diff --git a/MybatisLearning/http_test/target/classes/OKHttpClientBuilder.class b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder.class new file mode 100644 index 0000000..fe34d3a Binary files /dev/null and b/MybatisLearning/http_test/target/classes/OKHttpClientBuilder.class differ diff --git a/MybatisLearning/http_test/target/classes/SSLSocketClient$1.class b/MybatisLearning/http_test/target/classes/SSLSocketClient$1.class new file mode 100644 index 0000000..9801622 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/SSLSocketClient$1.class differ diff --git a/MybatisLearning/http_test/target/classes/SSLSocketClient$2.class b/MybatisLearning/http_test/target/classes/SSLSocketClient$2.class new file mode 100644 index 0000000..54a5ed5 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/SSLSocketClient$2.class differ diff --git a/MybatisLearning/http_test/target/classes/SSLSocketClient.class b/MybatisLearning/http_test/target/classes/SSLSocketClient.class new file mode 100644 index 0000000..98250c9 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/SSLSocketClient.class differ diff --git a/MybatisLearning/http_test/target/classes/StorageInfo.class b/MybatisLearning/http_test/target/classes/StorageInfo.class new file mode 100644 index 0000000..c139b15 Binary files /dev/null and b/MybatisLearning/http_test/target/classes/StorageInfo.class differ diff --git a/MybatisLearning/http_test/target/classes/Test.class b/MybatisLearning/http_test/target/classes/Test.class new file mode 100644 index 0000000..4ef452d Binary files /dev/null and b/MybatisLearning/http_test/target/classes/Test.class differ diff --git "a/JavaSE/JavaSE(\344\272\224).md" b/MybatisLearning/http_test/target/classes/application.properties similarity index 100% rename from "JavaSE/JavaSE(\344\272\224).md" rename to MybatisLearning/http_test/target/classes/application.properties diff --git a/MybatisLearning/mybatis_multitable/.idea/compiler.xml b/MybatisLearning/mybatis_multitable/.idea/compiler.xml new file mode 100644 index 0000000..5445593 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/.idea/encodings.xml b/MybatisLearning/mybatis_multitable/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/.idea/inspectionProfiles/Project_Default.xml b/MybatisLearning/mybatis_multitable/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6560a98 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/.idea/misc.xml b/MybatisLearning/mybatis_multitable/.idea/misc.xml new file mode 100644 index 0000000..4b661a5 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/.idea/uiDesigner.xml b/MybatisLearning/mybatis_multitable/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/.idea/workspace.xml b/MybatisLearning/mybatis_multitable/.idea/workspace.xml new file mode 100644 index 0000000..d97bf70 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/.idea/workspace.xml @@ -0,0 +1,773 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1615613121639 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No facets are configured + + + + + + + + + + + + + + + 1.8 + + + + + + + + mybatis_multitable + + + + + + + + 1.8 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/mybatis_multitable.iml b/MybatisLearning/mybatis_multitable/mybatis_multitable.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/mybatis_multitable.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/pom.xml b/MybatisLearning/mybatis_multitable/pom.xml new file mode 100644 index 0000000..24a36c5 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.lagou + mybatis_multitable + 1.0-SNAPSHOT + + + + + org.mybatis + mybatis + 3.4.5 + + + + mysql + mysql-connector-java + 5.1.6 + runtime + + + + junit + junit + 4.9 + + + + log4j + log4j + 1.2.12 + + + org.mybatis.caches + mybatis-redis + 1.0.0-beta2 + + + + + com.github.pagehelper + pagehelper + 3.7.5 + + + com.github.jsqlparser + jsqlparser + 0.9.1 + + + + tk.mybatis + mapper + 3.1.2 + + + + + + + + + src/main/java + + **/*.properties + **/*.xml + + false + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IOrderMapper.xml b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IOrderMapper.xml new file mode 100644 index 0000000..4becb8a --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IOrderMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IUserMapper.xml b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IUserMapper.xml new file mode 100644 index 0000000..187ca96 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/IUserMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IOrderMapper.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IOrderMapper.java new file mode 100644 index 0000000..5732cfb --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IOrderMapper.java @@ -0,0 +1,28 @@ +package com.lagou.mapper; + +import com.lagou.pojo.Order; +import com.lagou.pojo.User; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +@CacheNamespace//开启二级缓存 +public interface IOrderMapper { + + + /** + * 使用注解开发 + * @Results注解对应于 xml文件中的resultMap,每个实体如果是一对一关系,使用@One注解 + * 如果是一对多的关系(即集合),则是使用@many + * @return + */ + @Results({ + @Result(property = "id",column = "id"), + @Result(property = "orderTime",column = "order_time"), + @Result(property = "total",column = "total"), + @Result(property = "user",column = "uid",javaType = User.class, + one = @One(select = "com.lagou.mapper.IUserMapper.findUserById")) + }) + @Select("select * from orders") + List findAllOrderAndUser(); +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IUserMapper.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IUserMapper.java new file mode 100644 index 0000000..d626e03 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/IUserMapper.java @@ -0,0 +1,49 @@ +package com.lagou.mapper; + +import com.lagou.pojo.Order; +import com.lagou.pojo.User; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.cache.impl.PerpetualCache; +import org.mybatis.caches.redis.RedisCache; + +import java.util.List; + +/** + * 使用mybatis-redis作为二级缓存,这样可以实现分布式缓存(多台服务器同时请求) + * mybatis不能实现分布式缓存,其次底层是hashmap + */ +@CacheNamespace(implementation = RedisCache.class) +public interface IUserMapper { + //查询订单的同时还查询订单所属的用户 + List findOrderAndUser(); + + + //查询用户信息,同时查询每个用户关联订单信息 + List findAll(); + + /** + * 使用注解开发 + */ + //添加用户 + @Insert("insert into user values(#{id},#{userName})") + public void addUser(User user); + @Update("update user set username = #{userName} where id = #{id}") + public void updateUser(User user); + + @Select("select * from user") + public List selectAllUser(); + + @Delete("delete from user where id = #{id}") + public int delectUser(User user); + + + /** + * 禁用二级缓存,每次都从数据库中取 + * @param id + * @return + */ + @Options(useCache = false) + @Select("select * from user where id = #{id}") + public User findUserById(Integer id); + +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/UserMapper.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/UserMapper.java new file mode 100644 index 0000000..e0e8d23 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/mapper/UserMapper.java @@ -0,0 +1,10 @@ +package com.lagou.mapper; + +import com.lagou.pojo.User; +import tk.mybatis.mapper.common.Mapper; + +/** + * 通用mapper接口,继承mapper则可以增删改查 + */ +public interface UserMapper extends Mapper { +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/plugin/MyPlugin.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/plugin/MyPlugin.java new file mode 100644 index 0000000..064310e --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/plugin/MyPlugin.java @@ -0,0 +1,45 @@ +package com.lagou.plugin; + +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.plugin.*; + +import java.sql.Connection; +import java.util.Properties; + +/** + * 自定义插件:实现拦截器方法 + */ +@Intercepts({ + @Signature(type = StatementHandler.class,method = "prepare", + args = {Connection.class,Integer.class}) +}) +public class MyPlugin implements Interceptor { + /** + * 拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法 + * @param invocation + * @return + * @throws Throwable + */ + public Object intercept(Invocation invocation) throws Throwable { + System.out.println("对方法进行了增强。。。实现了分页 分表"); + return invocation.proceed();//原方法执行 + } + + /** + * 主要为了把当前拦截器生成代理存到拦截链中 + * @param + * @return + */ + public Object plugin(Object target) { + Object o = Plugin.wrap(target,this); + return o; + } + + /** + * 获取配置文件参数 + * @param properties + */ + public void setProperties(Properties properties) { + System.out.println("获取到的配置文件的参数:"+properties); + } +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/Order.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/Order.java new file mode 100644 index 0000000..869d872 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/Order.java @@ -0,0 +1,61 @@ +package com.lagou.pojo; + +public class Order { + private Integer id; + private String orderTime; + private Double total; + private Integer uid; + + private User user; + + @Override + public String toString() { + return "Order{" + + "id=" + id + + ", orderTime='" + orderTime + '\'' + + ", total=" + total + + ", uid=" + uid + + ", user=" + user + + '}'; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getOrderTime() { + return orderTime; + } + + public void setOrderTime(String orderTime) { + this.orderTime = orderTime; + } + + public Double getTotal() { + return total; + } + + public void setTotal(Double total) { + this.total = total; + } + + public Integer getUid() { + return uid; + } + + public void setUid(Integer uid) { + this.uid = uid; + } +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/User.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/User.java new file mode 100644 index 0000000..7b587db --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/pojo/User.java @@ -0,0 +1,52 @@ +package com.lagou.pojo; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.List; + +/** + * 开启二级缓存后,缓存的pojo需要实现反序列化,因为数据存储不一定在内存中,可能还在硬盘中,所以取数据的话就需要反序列化了 + * mybatis中的pojo都需要实现反序列化接口 + */ +@Table(name = "user") +public class User implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY)//主键自增 + private Integer id; + @Column(name = "username") + private String userName; + + private List orderList; + + public List getOrderList() { + return orderList; + } + + public void setOrderList(List orderList) { + this.orderList = orderList; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", userName='" + userName + '\'' + + '}'; + } +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/CacheTest.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/CacheTest.java new file mode 100644 index 0000000..1aa84ff --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/CacheTest.java @@ -0,0 +1,81 @@ +package com.lagou.test; + +import com.lagou.mapper.IOrderMapper; +import com.lagou.mapper.IUserMapper; +import com.lagou.pojo.User; +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 org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; + +public class CacheTest { + + private IUserMapper userMapper; + private SqlSession sqlSession; + private SqlSessionFactory sqlSessionFactory; + + @Before + public void beforePro() throws IOException { + InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + sqlSession = sqlSessionFactory.openSession(true); + userMapper = sqlSession.getMapper(IUserMapper.class); + } + + /** + * mybatis默认开启一级缓存,底层结构为hashmap。key为statementId+params+boundSql + * 如果做增删改操作,并进行事务的提交,就会刷新一级缓存 + */ + @Test + public void test(){ + User user = userMapper.findUserById(2); + User user1 = new User(); + user1.setId(11); + user1.setUserName("asad"); + userMapper.addUser(user1);//中间修改会刷新缓存 + //sqlSession.clearCache();//手动清除缓存 + + User user2 = userMapper.findUserById(2); + + System.out.println(user == user2);//开启了一级缓存,其实就是同一个对象 + } + + + /** + * 二级缓存test + * 二级缓存是基于namespace,就是同时操作usermapper下的不同的sql,且二级缓存是对同namespace下是共享的 + * 测试方法:根据不同的sqlsession来测试 + * 配置参数:@CacheNamespace 或者xml方式: + * Cache Hit Ratio:0.5,请求两次,命中一次,即0.5 + * + * Cause: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool + */ + @Test + public void test2(){ + SqlSession sqlSession1 = sqlSessionFactory.openSession(); + SqlSession sqlSession2 = sqlSessionFactory.openSession(); + SqlSession sqlSession3 = sqlSessionFactory.openSession(); + IUserMapper userMapper1 = sqlSession1.getMapper(IUserMapper.class); + IUserMapper userMapper2 = sqlSession2.getMapper(IUserMapper.class); + IUserMapper userMapper3 = sqlSession3.getMapper(IUserMapper.class); + + User user1 = userMapper1.findUserById(2); + sqlSession1.close();//清空一级缓存 + + User user = new User(); + user.setId(2); + user.setUserName("jjdjdj"); + userMapper2.updateUser(user);//对sqlsession2做了增删改查操作,那么二级缓存会清空刷新 + sqlSession2.commit();//需要提交事物 + + User user3 = userMapper3.findUserById(2); + System.out.println(user1 == user3);//fasle 原因是二级缓存不是缓存的对象,是保存数据,然后封装的对象,所以地址不一样 + sqlSession3.close(); + } + +} diff --git a/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/Testss.java b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/Testss.java new file mode 100644 index 0000000..6580f68 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/java/com/lagou/test/Testss.java @@ -0,0 +1,117 @@ +package com.lagou.test; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.lagou.mapper.IOrderMapper; +import com.lagou.mapper.IUserMapper; +import com.lagou.mapper.UserMapper; +import com.lagou.pojo.Order; +import com.lagou.pojo.User; +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 org.junit.Before; +import org.junit.Test; +import tk.mybatis.mapper.entity.Example; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class Testss { + + @Test + public void test1() throws IOException { + InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + SqlSession sqlSession = sqlSessionFactory.openSession(); + IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class); + List orders = userMapper.findOrderAndUser(); + for (Order order : orders) { + System.out.println(order); + } + } + + + @Test + public void test2() throws IOException { + InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + SqlSession sqlSession = sqlSessionFactory.openSession(); + IOrderMapper orderMapper = sqlSession.getMapper(IOrderMapper.class); + List orders = orderMapper.findAllOrderAndUser(); + System.out.println("查询订单!"); + for (Order order : orders) { + System.out.println(order); + } + IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class); + List users = userMapper.findAll(); + System.out.println("查询用户!"); + for (User user : users) { + System.out.println(user); + } + } + + private IUserMapper userMapper; + private IOrderMapper orderMapper; + + @Before + public void beforePro() throws IOException { + InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + SqlSession sqlSession = sqlSessionFactory.openSession(true); + userMapper = sqlSession.getMapper(IUserMapper.class); + orderMapper = sqlSession.getMapper(IOrderMapper.class); + } + + + @Test + public void test3(){ + User user = new User(); + user.setId(10); + user.setUserName("mmm"); + //userMapper.addUser(user); + user.setUserName("adasa"); + userMapper.updateUser(user); + } + + @Test + public void test4(){ + List orders = orderMapper.findAllOrderAndUser(); + for (Order order : orders) { + System.out.println(order); + } + } + + /** + * pageHelper插件使用 + */ + @Test + public void test5(){ + PageHelper.startPage(1,1); + List orders = orderMapper.findAllOrderAndUser(); + for (Order order : orders) { + System.out.println(order); + } + PageInfo pageInfo = new PageInfo(orders); + } + + @Test + public void test6() throws IOException { + InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + SqlSession sqlSession = sqlSessionFactory.openSession(); + UserMapper userMapper = sqlSession.getMapper(UserMapper.class); + User user = new User(); + user.setId(1); + User user1 = userMapper.selectOne(user); + System.out.println(user1); + + + Example example = new Example(User.class); + example.createCriteria().andEqualTo("id",1).andEqualTo("username","ljkd"); + List users = userMapper.selectByExample(example); + } + +} diff --git a/MybatisLearning/mybatis_multitable/src/main/resources/IUserMapper.xml b/MybatisLearning/mybatis_multitable/src/main/resources/IUserMapper.xml new file mode 100644 index 0000000..5b387e9 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/resources/IUserMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/resources/jdbc.properties b/MybatisLearning/mybatis_multitable/src/main/resources/jdbc.properties new file mode 100644 index 0000000..b517f8e --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/resources/jdbc.properties @@ -0,0 +1,5 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/test +jdbc.username=root +jdbc.password=123guojing + diff --git a/MybatisLearning/mybatis_multitable/src/main/resources/log4j.properties b/MybatisLearning/mybatis_multitable/src/main/resources/log4j.properties new file mode 100644 index 0000000..e499871 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/resources/log4j.properties @@ -0,0 +1,15 @@ +### direct log messages to stdout ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### direct messages to file mylog.log ### +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=c:/mylog.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### set log levels - for more verbose logging change 'info' to 'debug' ### + +log4j.rootLogger=debug, stdout \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/resources/redis.properties b/MybatisLearning/mybatis_multitable/src/main/resources/redis.properties new file mode 100644 index 0000000..631705e --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/resources/redis.properties @@ -0,0 +1,5 @@ +redis.host=localhost +redis.port=6379 +redis.connectionTimeout=5000 +redis.password= +redis.database=0 \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/src/main/resources/sqlMapConfig.xml b/MybatisLearning/mybatis_multitable/src/main/resources/sqlMapConfig.xml new file mode 100644 index 0000000..08021d2 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/src/main/resources/sqlMapConfig.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MybatisLearning/mybatis_multitable/target/classes/IUserMapper.xml b/MybatisLearning/mybatis_multitable/target/classes/IUserMapper.xml new file mode 100644 index 0000000..5b387e9 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/IUserMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IOrderMapper.xml b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IOrderMapper.xml new file mode 100644 index 0000000..4becb8a --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IOrderMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IUserMapper.xml b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IUserMapper.xml new file mode 100644 index 0000000..187ca96 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/IUserMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IOrderMapper.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IOrderMapper.class new file mode 100644 index 0000000..0c85e51 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IOrderMapper.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IUserMapper.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IUserMapper.class new file mode 100644 index 0000000..5e5c731 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/IUserMapper.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/UserMapper.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/UserMapper.class new file mode 100644 index 0000000..c022be3 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/mapper/UserMapper.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/plugin/MyPlugin.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/plugin/MyPlugin.class new file mode 100644 index 0000000..746dfc4 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/plugin/MyPlugin.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/Order.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/Order.class new file mode 100644 index 0000000..f75cee4 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/Order.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/User.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/User.class new file mode 100644 index 0000000..7b6b539 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/pojo/User.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/CacheTest.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/CacheTest.class new file mode 100644 index 0000000..656ca33 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/CacheTest.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/Testss.class b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/Testss.class new file mode 100644 index 0000000..6aa0f81 Binary files /dev/null and b/MybatisLearning/mybatis_multitable/target/classes/com/lagou/test/Testss.class differ diff --git a/MybatisLearning/mybatis_multitable/target/classes/jdbc.properties b/MybatisLearning/mybatis_multitable/target/classes/jdbc.properties new file mode 100644 index 0000000..b517f8e --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/jdbc.properties @@ -0,0 +1,5 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/test +jdbc.username=root +jdbc.password=123guojing + diff --git a/MybatisLearning/mybatis_multitable/target/classes/log4j.properties b/MybatisLearning/mybatis_multitable/target/classes/log4j.properties new file mode 100644 index 0000000..e499871 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/log4j.properties @@ -0,0 +1,15 @@ +### direct log messages to stdout ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### direct messages to file mylog.log ### +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=c:/mylog.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### set log levels - for more verbose logging change 'info' to 'debug' ### + +log4j.rootLogger=debug, stdout \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/target/classes/redis.properties b/MybatisLearning/mybatis_multitable/target/classes/redis.properties new file mode 100644 index 0000000..631705e --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/redis.properties @@ -0,0 +1,5 @@ +redis.host=localhost +redis.port=6379 +redis.connectionTimeout=5000 +redis.password= +redis.database=0 \ No newline at end of file diff --git a/MybatisLearning/mybatis_multitable/target/classes/sqlMapConfig.xml b/MybatisLearning/mybatis_multitable/target/classes/sqlMapConfig.xml new file mode 100644 index 0000000..08021d2 --- /dev/null +++ b/MybatisLearning/mybatis_multitable/target/classes/sqlMapConfig.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MybatisLearning/mybatis_quickstart/.idea/compiler.xml b/MybatisLearning/mybatis_quickstart/.idea/compiler.xml new file mode 100644 index 0000000..d808334 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/.idea/encodings.xml b/MybatisLearning/mybatis_quickstart/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/.idea/inspectionProfiles/Project_Default.xml b/MybatisLearning/mybatis_quickstart/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6560a98 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/.idea/misc.xml b/MybatisLearning/mybatis_quickstart/.idea/misc.xml new file mode 100644 index 0000000..4b661a5 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/.idea/uiDesigner.xml b/MybatisLearning/mybatis_quickstart/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/.idea/workspace.xml b/MybatisLearning/mybatis_quickstart/.idea/workspace.xml new file mode 100644 index 0000000..096beb1 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/.idea/workspace.xml @@ -0,0 +1,662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into user values (#{id},#{userName}) + + + + + delete from user where id = #{abc} + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/src/main/resources/jdbc.properties b/MybatisLearning/mybatis_quickstart/src/main/resources/jdbc.properties new file mode 100644 index 0000000..b517f8e --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/src/main/resources/jdbc.properties @@ -0,0 +1,5 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/test +jdbc.username=root +jdbc.password=123guojing + diff --git a/MybatisLearning/mybatis_quickstart/src/main/resources/log4j.properties b/MybatisLearning/mybatis_quickstart/src/main/resources/log4j.properties new file mode 100644 index 0000000..e499871 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/src/main/resources/log4j.properties @@ -0,0 +1,15 @@ +### direct log messages to stdout ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### direct messages to file mylog.log ### +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=c:/mylog.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### set log levels - for more verbose logging change 'info' to 'debug' ### + +log4j.rootLogger=debug, stdout \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/src/main/resources/sqlMapConfig.xml b/MybatisLearning/mybatis_quickstart/src/main/resources/sqlMapConfig.xml new file mode 100644 index 0000000..9b58dd5 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/src/main/resources/sqlMapConfig.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MybatisLearning/mybatis_quickstart/target/classes/UserMapper.xml b/MybatisLearning/mybatis_quickstart/target/classes/UserMapper.xml new file mode 100644 index 0000000..206f42b --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/target/classes/UserMapper.xml @@ -0,0 +1,50 @@ + + + + + + + select * from user + + + + + + + insert into user values (#{id},#{userName}) + + + + + delete from user where id = #{abc} + + + + + + + + + \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/IUserDao.class b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/IUserDao.class new file mode 100644 index 0000000..51f03c1 Binary files /dev/null and b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/IUserDao.class differ diff --git a/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/UserDaoImpl.class b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/UserDaoImpl.class new file mode 100644 index 0000000..2a7172b Binary files /dev/null and b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/dao/UserDaoImpl.class differ diff --git a/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/pojo/User.class b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/pojo/User.class new file mode 100644 index 0000000..916ce0c Binary files /dev/null and b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/pojo/User.class differ diff --git a/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/test/test.class b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/test/test.class new file mode 100644 index 0000000..67e9a7c Binary files /dev/null and b/MybatisLearning/mybatis_quickstart/target/classes/com/lagou/test/test.class differ diff --git a/MybatisLearning/mybatis_quickstart/target/classes/jdbc.properties b/MybatisLearning/mybatis_quickstart/target/classes/jdbc.properties new file mode 100644 index 0000000..b517f8e --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/target/classes/jdbc.properties @@ -0,0 +1,5 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/test +jdbc.username=root +jdbc.password=123guojing + diff --git a/MybatisLearning/mybatis_quickstart/target/classes/log4j.properties b/MybatisLearning/mybatis_quickstart/target/classes/log4j.properties new file mode 100644 index 0000000..e499871 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/target/classes/log4j.properties @@ -0,0 +1,15 @@ +### direct log messages to stdout ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### direct messages to file mylog.log ### +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=c:/mylog.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n + +### set log levels - for more verbose logging change 'info' to 'debug' ### + +log4j.rootLogger=debug, stdout \ No newline at end of file diff --git a/MybatisLearning/mybatis_quickstart/target/classes/sqlMapConfig.xml b/MybatisLearning/mybatis_quickstart/target/classes/sqlMapConfig.xml new file mode 100644 index 0000000..9b58dd5 --- /dev/null +++ b/MybatisLearning/mybatis_quickstart/target/classes/sqlMapConfig.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MybatisLearning/pom.xml b/MybatisLearning/pom.xml new file mode 100644 index 0000000..a91c065 --- /dev/null +++ b/MybatisLearning/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + com.learning + MybatisLearing + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..535c30f --- /dev/null +++ b/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + com.learning + JavaSeniorEngineer + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/JDK\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/JDK\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204.md" deleted file mode 100644 index 0640f74..0000000 --- "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/JDK\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ /dev/null @@ -1,292 +0,0 @@ -# 以下是Java中常用的数据结构的基础知识 - - - -Java集合类主要由两个根接口`Collection`和`Map`派生出来的,`Collection`派生出了三个子接口:`List`、`Set`、`Queue`(Java5新增的队列) - -因此Java集合大致也可分成`List`、`Set`、`Queue`、`Map`四种接口体系,(注意:Map不是Collection的子接口) - -其中List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问; - -Queue是队列集合;Map代表的是存储key-value对的集合,可根据元素的key来访问value - -上图中淡绿色背景覆盖的是集合体系中常用的实现类,分别是`ArrayList`、`LinkedList`、`ArrayQueue`、`HashSet`、`TreeSet`、`HashMap`、`TreeMap`等实现类 - -# 1 List家族 -List接口继承图: - - - -`JDK`中的List家族主要包括了`ArrayList`、 `LinkedList`、`Vector`、`CopyOnWriteArrayList`、`UnmodifiableList` 、`SynchronizedList` - -## 1.1 List - -List集合是有序的,Developer可对其中每个元素的插入位置进行精确地控制,可以通过索引来访问元素,遍历元素 - -List类在Java.awt包里,List在java.util包里,但使用时是用List\ - -因为List是列表,本质上是一个数组,没有类型,使用List\泛型主要为了列表的数据类型 - -### 1.1.1 代码方法实战 - -```java - void demo_1(){ - //实例化List - List list = new ArrayList<>(); - //实例化直接赋值 - List list1 = Arrays.asList("a","c","m","d"); - //添加元素 - list.add("a"); - System.out.println("demo_1添加 a 后输出list:"+list);//output:[a] - list.add("b"); - System.out.println("demo_1添加 a b 后输出list:"+list);//output:[a, b] - list.add(2,"c");//可以看出本质上是个数组,集合有序,每次添加都在index后面添加 - list.add("d"); - System.out.println("添加 c d 后输出list:"+list); - //修改元素 - list.set(2,"e"); - System.out.println("修改元素 2 后输出list:"+list); - list.remove(2); - System.out.println("输出list:"+list); - list.remove("c");//remove(object)意思就是删除list中的元素 - System.out.println(" 后输出list:"+list); - //查询 - String element = list.get(1);//get(index)获取第几个元素 - int index = list.indexOf("a");//indexOf(object)获取list中元素的位置 - System.out.println("输出element index:"+element+" "+index);//output:b 0 - //Java8处理输出 - List collect = list.stream().collect(Collectors.toList()); - System.out.println(" 后输出collect:"+collect);//output:[a, b, d] - list.removeAll(list1); - System.out.println(" 后removeAlllist:"+list);//output:[b] - //遍历list-forEach方法,Java8新特性 - list.forEach(System.out::println);//output:b - list.forEach(item->{ - System.out.println(item);//item就是list中的元素,便于对括号里面的元素做处理 - });//output:b - - for(String item : list){ - System.out.print(item + " "); - }//output:b - - } -``` - -**注意**:输出的是`["a","b","c"]`,带有`[]` - -### 1.1.2 List常用方法总结 -#### (1)void add(Object element) -向列表的尾部添加指定的元素 - -#### (2)int size() -返回列表中的元素个数 - -#### (3)E get(int index) -返回列表中指定位置的元素,index从0开始 - -#### (4)void add(int index, Object element) -在列表的指定位置插入指定元素 - -#### (5)void set(int i, Object element) -将索引i位置元素替换为元素element并返回被替换的元素 - -#### (6)void clear() -从列表中移除所有元素 - -#### (7)boolean isEmpty() -判断列表是否包含元素,不包含元素则返回 true,否则返回false - -#### (8)iterator() -返回按适当顺序在列表的元素上进行迭代的迭代器 - -#### (9)boolean contains(Object o) -如果列表包含指定的元素,则返回 true - -#### (10)E remove(int index) -移除列表中指定位置的元素,并返回被删元素 - -#### (11)boolean remove(Object o) -移除集合中第一次出现的指定元素,移除成功返回true,否则返回false - -#### (12)void forEach(ConSumer action) -forEach是for的增强版 其中System.out::println这段代码其实就是Consumer接口的一个实现方式 - -```java -list.forEach(System.out::println);//output:b - list.forEach(item->{ - System.out.println(item);//item就是list中的元素,便于对括号里面的元素做处理 - });//output:b -``` -#### (13)toArray - -```java - - //方法1,使用不带参数的toArray方法 - String[] arr1=new String[list.size()]; - list.toArray(arr);//此时arr就有了list中的值了 - //方法2,使用带参数的toArray方法 - String[] arr2=(String[])list.toArray(new String[0]);//参数含义的解释:要存储列表中元素的数组,如果它足够大的话;否则为此目的分配一个运行时类型相同的新数组。 - - -``` -**注意:** 下面方法写法错误 - -> String[]arr=(String[])list.toArray();//会出现java.lang.ClassCastException - -## 1.2 ArrayList - -ArrayList是集合的一种实现,实现了接口`List`,List接口继承了`Collection`接口,而Collection是所有集合类的父类。ArrayList使用非常广泛,不论是数据库表查询,excel导入解析,还是网站数据爬取都需要使用到,了解ArrayList原理及使用方法显得非常重要。 - -### 1.2.1 定义一个ArrayList -```java -List list = new ArrayList<>(); -//默认创建一个ArrayList集合 -List list = new ArrayList<>(); -//创建一个初始化长度为100的ArrayList集合 -List initlist = new ArrayList<>(100); -//将其他类型的集合转为ArrayList -List setList = new ArrayList<>(new HashSet()); -``` - -### 1.2.2 ArrayList源码解析 - -```java -public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable { - /** - * Default initial capacity. - */ - private static final int DEFAULT_CAPACITY = 10; - - /** - * Shared empty array instance used for empty instances. - */ - private static final Object[] EMPTY_ELEMENTDATA = {}; - - /** - * Shared empty array instance used for default sized empty instances. We - * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when - * first element is added. - */ - private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; - - /** - * The array buffer into which the elements of the ArrayList are stored. - * The capacity of the ArrayList is the length of this array buffer. Any - * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA - * will be expanded to DEFAULT_CAPACITY when the first element is added. - */ - transient Object[] elementData; // non-private to simplify nested class access - - /** - * The size of the ArrayList (the number of elements it contains). - * - * @serial - */ - private int size; - - /** - * Constructs an empty list with the specified initial capacity. - * - * @param initialCapacity the initial capacity of the list - * @throws IllegalArgumentException if the specified initial capacity - * is negative - */ - public ArrayList(int initialCapacity) { - if (initialCapacity > 0) { - this.elementData = new Object[initialCapacity]; - } else if (initialCapacity == 0) { - this.elementData = EMPTY_ELEMENTDATA; - } else { - throw new IllegalArgumentException("Illegal Capacity: "+ - initialCapacity); - } - } - - /** - * Constructs an empty list with an initial capacity of ten. - */ - public ArrayList() { - this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; - } - - /** - * Constructs a list containing the elements of the specified - * collection, in the order they are returned by the collection's - * iterator. - * - * @param c the collection whose elements are to be placed into this list - * @throws NullPointerException if the specified collection is null - */ - public ArrayList(Collection c) { - elementData = c.toArray(); - if ((size = elementData.length) != 0) { - // c.toArray might (incorrectly) not return Object[] (see 6260652) - if (elementData.getClass() != Object[].class) - elementData = Arrays.copyOf(elementData, size, Object[].class); - } else { - // replace with empty array. - this.elementData = EMPTY_ELEMENTDATA; - } - } -} -``` -从源码可以看出,ArrayList非线程安全,底层是一个`Object[] -elementData`,添加到ArrayList中的数据保存在了elementData属性中, -有第三个构造函数:`ArrayList()`、`ArrayList(int -initialCapacity)`、`ArrayList(Collection c)`。 - -+ 当调用`new ArrayList<>()`时,将一个空数组{}赋值给了elementData,这个时候集合的长度size为默认长度0; -+ 当调用`new ArrayList<>(100)`时,根据传入的长度,new一个Object[100]赋值给elementData,当然如果玩儿的话,传了一个0,那么将一个空数组{}赋值给了elementData; -+ 当调用`new ArrayList<>(new HashSet())`时,根据源码,我们可知,可以传递任何实现了Collection接口的类,将传递的集合调用`toArray()`方法转为数组内赋值给elementData; - - -#### tips:线程安全与线程不安全理解 -线程安全就是`多线程访问`时,采用了`加锁`机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 - -线程不安全就是`不提供数据访问保护`,有可能出现多个线程先后更改数据造成所得到的数据是`脏数据` - -##### 概念: - -如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 -或者说:一个类或者程序所提供的接口对于线程来说是`原子操作`或者多个线程之间的切换不会导致该接口的执行结果存在`二义性`,也就是说我们不用考虑同步的问题。 -线程安全问题都是由`全局变量`及`静态变量`引起的。 -若每个线程中对`全局变量`、`静态变量`只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑`线程同步`,否则的话就可能影响线程安全。 - -##### 安全性: - -比如一个 `ArrayList` 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。 -在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1; -而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。 -那好,我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。 - -##### 不可变: - -不可变的对象**一定**是**线程安全**的,并且永远也不需要额外的同步 -因为一个不可变的对象只要构建正确,其外部可见状态永远也不会改变,永远也不会看到它处于不一致的状态。Java -类库中大多数基本数值类如 `Integer` 、 `String` 和 `BigInteger` 都是不可变的。 -需要注意的是,对于Integer,该类不提供add方法,加法是使用+来直接操作。而+操作是不具线程安全的。这是提供原子操作类AtomicInteger的原。 - -### 1.2.2 数组、ArrayList中的区别 -数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单,比如: -```java -string[] s=new string[3]; -//赋值 - s[0]="a"; s[1]="b"; s[2]="c"; -//修改 - s[1]="b1"; -``` -总所周知,数组在中间插入数据时,会移动后面的数据。而且在声明数组时,必须指明数组长度,长度过长会造成内存溢出,长度过短,会造成数据溢出错误,所以ArrayList对象可以克服这些缺点。 - -## 1.3 LinkedList - - -## 1.4 Vector -## 1.5 CopyOnWriteArrayList -## 1.6 UnmodifiableList -## 1.7 SynchronizedList - -# 2 Set家族 -## 2.1 Set -## 2.2 HashSet -### 2.2.1 HashSet集合是不支持排序的,但是我们可以通过TreeSet集合对其进行间接排序 -https://blog.csdn.net/jmj18756235518/article/details/81557356 diff --git "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\346\223\215\344\275\234\347\263\273\347\273\237.md" "b/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\346\223\215\344\275\234\347\263\273\347\273\237.md" deleted file mode 100644 index e69de29..0000000 diff --git "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\346\225\260\346\215\256\347\273\223\346\236\204.md" deleted file mode 100644 index 009334b..0000000 --- "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ /dev/null @@ -1,177 +0,0 @@ -# 1 时间复杂度 - -## 1.1 复杂度:如何衡量程序运行的效率? - -## 1.2 复杂度是什么 - -`复杂度是衡量代码运行效率的重要的度量因素`。在介绍复杂度之前,有必要先看一下复杂度和计算机实际任务处理效率的关系,从而了解降低复杂度的必要性。 -计算机通过一个个程序去执行计算任务,也就是对输入数据进行加工处理,并最终得到结果的过程。每个程序都是由代码构成的。可见,编写代码的核心就是要完成计算。但对于同一个计算任务,不同计算方法得到结果的过程复杂程度是不一样的,这对你实际的任务处理效率就有了非常大的影响。 -举个例子,你要在一个在线系统中实时处理数据。假设这个系统平均每分钟会新增 300M 的数据量。如果你的代码不能在 1 分钟内完成对这 300M 数据的处理,那么这个系统就会发生时间爆炸和空间爆炸。表现就是,电脑执行越来越慢,直到死机。因此,我们需要讲究合理的计算方法,去通过尽可能低复杂程度的代码完成计算任务。 - -那提到降低复杂度,我们首先需要知道怎么衡量复杂度。而在实际衡量时,我们通常会围绕以下2 个维度进行。`首先,这段代码消耗的资源是什么`。一般而言,代码执行过程中会消耗计算时间和计算空间,那需要衡量的就是时间复杂度和空间复杂度。 -我举一个实际生活中的例子。某个十字路口没有建立立交桥时,所有车辆通过红绿灯分批次行驶通过。当大量汽车同时过路口的时候,就会分别消耗大家的时间。但建了立交桥之后,所有车辆都可以同时通过了,因为立交桥的存在,等于是消耗了空间资源,来换取了时间资源。 - -`其次,这段代码对于资源的消耗是多少`。我们不会关注这段代码对于资源消耗的绝对量,因为不管是时间还是空间,它们的消耗程度都与输入的数据量高度相关,输入数据少时消耗自然就少。为了更客观地衡量消耗程度,我们通常会关注时间或者空间消耗量与输入数据量之间的关系。 -好,现在我们已经了解了衡量复杂度的两个纬度,那应该如何去计算复杂度呢? -`复杂度是一个关于输入数据量 n 的函数`。假设你的代码复杂度是 f(n),那么就用个大写字母 O 和括号,把 f(n) 括起来就可以了,即 O(f(n))。例如,O(n) 表示的是,复杂度与计算实例的个数 n 线性相关;O(logn) 表示的是,复杂度与计算实例的个数 n 对数相关。 -通常,复杂度的计算方法遵循以下几个原则: - -首先,`复杂度与具体的常系数无关`,例如 O(n) 和 O(2n) 表示的是同样的复杂度。我们详细分析下,O(2n) 等于 O(n+n),也等于 O(n) + O(n)。也就是说,一段 O(n) 复杂度的代码只是先后执行两遍 O(n),其复杂度是一致的。 -其次,`多项式级的复杂度相加的时候,选择高者作为结果`,例如 O(n²)+O(n) 和 O(n²) 表示的是同样的复杂度。具体分析一下就是,O(n²)+O(n) = O(n²+n)。随着 n 越来越大,二阶多项式的变化率是要比一阶多项式更大的。因此,只需要通过更大变化率的二阶多项式来表征复杂度就可以了。 - -值得一提的是,`O(1) 也是表示一个特殊复杂度`,含义为某个任务通过有限可数的资源即可完成。此处有限可数的具体意义是,`与输入数据量 n 无关`。 -例如,你的代码处理 10 条数据需要消耗 5 个单位的时间资源,3 个单位的空间资源。处理 1000 条数据,还是只需要消耗 5 个单位的时间资源,3 个单位的空间资源。那么就能发现资源消耗与输入数据量无关,就是 O(1) 的复杂度。 -为了方便你理解不同计算方法对复杂度的影响,我们来看一个代码任务:对于输入的数组,输出与之逆序的数组。例如,输入 a=[1,2,3,4,5],输出 [5,4,3,2,1]。 -先看方法一,建立并初始化数组 b,得到一个与输入数组等长的全零数组。通过一个 for 循环,从左到右将 a 数组的元素,从右到左地赋值到 b 数组中,最后输出数组 b 得到结果。 -### 1.2.1 方法一: -```java -public void s1_1() { - int a[] = { 1, 2, 3, 4, 5 }; - int b[] = new int[5]; - for (int i = 0; i < a.length; i++) { - b[i] = a[i]; - } - for (int i = 0; i < a.length; i++) { - b[a.length - i - 1] = a[i]; - } - System.out.println(Arrays.toString(b)); -} -``` -这段代码的输入数据是 a,数据量就等于数组 a 的长度。代码中有两个 for 循环,作用分别是给b 数组初始化和赋值,其执行次数都与输入数据量相等。因此,代码的时间复杂度就是 O(n)+O(n),也就是 O(n)。 -空间方面主要体现在计算过程中,对于存储资源的消耗情况。上面这段代码中,我们定义了一个新的数组 b,它与输入数组 a 的长度相等。因此,空间复杂度就是 O(n)。 -`接着我们看一下第二种编码方法`,它定义了缓存变量 tmp,接着通过一个 for 循环,从 0 遍历到a 数组长度的一半(即 len(a)/2)。每次遍历执行的是什么内容?就是交换首尾对应的元素。最后打印数组 a,得到结果。 - -### 1.2.2 方法二 - -```java -public void s1_2() { - int a[] = { 1, 2, 3, 4, 5 }; - int tmp = 0; - for (int i = 0; i < (a.length / 2); i++) { - tmp = a[i]; - a[i] = a[a.length - i - 1]; - a[a.length - i - 1] = tmp; - } - System.out.println(Arrays.toString(a)); -} -``` - -这段代码包含了一个 for 循环,执行的次数是数组长度的一半,时间复杂度变成了 O(n/2)。根据复杂度与具体的常系数无关的性质,这段代码的时间复杂度也就是 O(n)。 -空间方面,我们定义了一个 tmp 变量,它与数组长度无关。也就是说,输入是 5 个元素的数组,需要一个 tmp 变量;输入是 50 个元素的数组,依然只需要一个 tmp 变量。因此,空间复杂度与输入数组长度无关,即 O(1)。 -可见,`对于同一个问题,采用不同的编码方法,对时间和空间的消耗是有可能不一样的`。因此,工程师在写代码的时候,一方面要完成任务目标;另一方面,也需要考虑时间复杂度和空间复杂度,以求用尽可能少的时间损耗和尽可能少的空间损耗去完成任务。 - -## 1.3 时间复杂度与代码结构的关系 - -好了,通过前面的内容,相信你已经对时间复杂度和空间复杂度有了很好的理解。从本质来看,时间复杂度与代码的结构有着非常紧密的关系;而空间复杂度与数据结构的设计有关,关于这一点我们会在下一讲进行详细阐述。接下来我先来系统地讲一下时间复杂度和代码结构的关系。 -`代码的时间复杂度,与代码的结构有非常强的关系`,我们一起来看一些具体的例子。 -例 1,定义了一个数组 a = [1, 4, 3],查找数组 a 中的最大值,代码如下: - -```java -public void s1_3() { - int a[] = { 1, 4, 3 }; - int max_val = -1; - for (int i = 0; i < a.length; i++) { - if (a[i] > max_val) { - max_val = a[i]; - } - } - System.out.println(max_val); -} -``` - -这个例子比较简单,实现方法就是,暂存当前最大值并把所有元素遍历一遍即可。因为代码的结构上需要使用一个 for 循环,对数组所有元素处理一遍,所以时间复杂度为 O(n)。 -例2,下面的代码定义了一个数组 a = [1, 3, 4, 3, 4, 1, 3],并会在这个数组中查找出现次数最多的那个数字: - -```java -public void s1_4() { - int a[] = { 1, 3, 4, 3, 4, 1, 3 }; - int val_max = -1; - int time_max = 0; - int time_tmp = 0; - for (int i = 0; i < a.length; i++) { - time_tmp = 0; - for (int j = 0; j < a.length; j++) { - if (a[i] == a[j]) { - time_tmp += 1; - } - if (time_tmp > time_max) { - time_max = time_tmp; - val_max = a[i]; - } - } - } - System.out.println(val_max); -} -``` - -这段代码中,我们采用了双层循环的方式计算:第一层循环,我们对数组中的每个元素进行遍历;第二层循环,对于每个元素计算出现的次数,并且通过当前元素次数 time_tmp 和全局最大次数变量 time_max 的大小关系,持续保存出现次数最多的那个元素及其出现次数。由于是双层循环,这段代码在时间方面的消耗就是 n*n 的复杂度,也就是 O(n²)。 -在这里,我们给出一些经验性的结论: - -一个顺序结构的代码,时间复杂度是 O(1)。 -二分查找,或者更通用地说是采用分而治之的二分策略,时间复杂度都是 O(logn)。这个我们会在后续课程讲到。 -一个简单的 for 循环,时间复杂度是 O(n)。 -两个顺序执行的 for 循环,时间复杂度是 O(n)+O(n)=O(2n),其实也是 O(n)。 -两个嵌套的 for 循环,时间复杂度是 O(n²)。 - -有了这些基本的结论,再去分析代码的时间复杂度将会轻而易举。 -## 1.4 降低时间复杂度的必要性 -很多新手的工程师,对降低时间复杂度并没有那么强的意识。这主要是在学校或者实验室中,参加的课程作业或者科研项目,普遍都不是实时的、在线的工程环境。 -实际的在线环境中,用户的访问请求可以看作一个流式数据。假设这个数据流中,每个访问的平均时间间隔是 t。如果你的代码无法在 t 时间内处理完单次的访问请求,那么这个系统就会一波未平一波又起,最终被大量积压的任务给压垮。这就要求工程师必须通过优化代码、优化数据结构,来降低时间复杂度。 -为了更好理解,我们来看一些数据。假设某个计算任务需要处理 10万 条数据。你编写的代码: - -如果是 O(n²) 的时间复杂度,那么计算的次数就大概是 100 亿次左右。 -如果是 O(n),那么计算的次数就是 10万 次左右。 -如果这个工程师再厉害一些,能在 O(log n) 的复杂度下完成任务,那么计算的次数就是 17 次左右(log 100000 = 16.61,计算机通常是二分法,这里的对数可以以 2 为底去估计)。 - -数字是不是一下子变得很悬殊?通常在小数据集上,时间复杂度的降低在绝对处理时间上没有太多体现。但在当今的大数据环境下,时间复杂度的优化将会带来巨大的系统收益。而这是优秀工程师必须具备的工程开发基本意识。 - -## 1.5 总结 - -OK,今天的内容到这儿就结束了。相信你对复杂度的概念有了进一步的认识。 -复杂度通常包括时间复杂度和空间复杂度。在具体计算复杂度时需要注意以下几点。 - -它与具体的常系数无关,O(n) 和 O(2n) 表示的是同样的复杂度。 -复杂度相加的时候,选择高者作为结果,也就是说 O(n²)+O(n) 和 O(n²) 表示的是同样的复杂度。 -O(1) 也是表示一个特殊复杂度,即任务与算例个数 n 无关。 - -复杂度细分为时间复杂度和空间复杂度,其中时间复杂度与代码的结构设计高度相关;空间复杂度与代码中数据结构的选择高度相关。会计算一段代码的时间复杂度和空间复杂度,是工程师的基本功。这项技能你在实际工作中一定会用到,甚至在参加互联网公司面试的时候,也是面试中的必考内容。 -关于复杂度的评估,需要你深入理解本节课的知识点。最后,你工作中有遇到过关于计算复杂度的哪些实际问题吗?你又是如何解决的?欢迎你在留言区和我分享。 - -# 2 数据结构 - -## 2.1 代码对数据处理主要分为三个部分:增、删、查 -+ 找到要处理的数据。这就是按照某些条件进行**查找**。 - + 其中查找又分为按`索引值查找`、`按条件查找` -+ 把结果存到一个新的内存空间中。这就是在现有数据上进行**新增**。 -+ 把结果存到一个已使用的内存空间中。这需要先**删除**内存空间中的已有数据,再新增新的数据。 -明白数据的三个操作,再做算法时可以对其优化,选择合理的数据结构。 - -## 2.2 查找 - -### 2.2.1 例一:找到数组中的第二个元素并输出 - -对于数组,其中先根据索引值index查找到第二个数据元素再输出,如a[1],此时时间复杂度为O(1) -如果是链表,则依次从头结点遍历整个链表,此时时间复杂度为O(n) - -### 2.2.2 例二:根据数值条件查找,查找数组里为9的元素是否存在 -此时对于数组和链表都束手无措了,只能遍历整个数组或者链表进行查找,此时时间复杂度为O(n)。 -那么有没有更低的时间复杂度方式呢,就需要用到数据结构进行优化。采用把数组转换为字典,以保存元素及其出现次数的 k-v 映射关系。而在每次的循环中,都需要对当前遍历的元素,去查找它是否在字典中出现过。这里就是很实际的按照元素数值查找的例子。如果借助字典的数据类型,这个例子的查找问题,就可以在 O(1) 的时间复杂度内完成了。 -## 2.3 新增 -### 2.3.1 在复杂数据结构的最后新增 - -此时需要查找该数据结构的最后位置,再赋值或插入一条数据即可 -比如数组和单链表,在最后新增不用移动数据,时间复杂度为O(1) - -### 2.3.2 在复杂数据结构的中间新增 - -比如对长度为4的数组,在第二个元素中插入一个数据,则需要查找第二个数据,再新增数组,最后还需要移动原来第三第四的位置数据 - -## 2.4 删除 -### (1)是在这个复杂数据结构的最后,删除一条数据 -### (2)是在这个复杂数据结构的中间某个位置,删除一条数据 - -数据处理的基本操作只有 3 个,分别是`增`、`删`、`查`。其中,增和删又可以细分为在数据结构中间的增和删,以及在数据结构最后的增和删。区别就在于原数据的位置是否发生改变。查找又可以细分为按照位置条件的查找和按照数据数值特征的查找。几乎所有的数据处理,都是这些基本操作的组合和叠加。 -在实际的工作中,如果你不知道该用什么数据结构的时候,就一定要回归问题本源。从数据需要被处理的动作出发。只有明确了会有什么动作,才能找到最合适的解决方法。 - -# 3 Java常用的数据结构 - diff --git "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206.md" "b/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206.md" deleted file mode 100644 index e69de29..0000000 diff --git "a/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/\345\233\233\345\244\247\345\217\221\346\230\216\346\200\273\350\247\210/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" deleted file mode 100644 index e69de29..0000000 diff --git "a/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/MySQL\350\277\233\351\230\266\346\212\200\346\234\257.md" "b/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/MySQL\350\277\233\351\230\266\346\212\200\346\234\257.md" deleted file mode 100644 index e29e30a..0000000 --- "a/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/MySQL\350\277\233\351\230\266\346\212\200\346\234\257.md" +++ /dev/null @@ -1,3 +0,0 @@ -# 本章节为MySQL进阶技术,以下为思维导图 - -数据库进阶学习导图 \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/Mysql\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/Mysql\345\237\272\347\241\200\347\237\245\350\257\206.md" deleted file mode 100644 index 4338c9e..0000000 --- "a/\346\225\260\346\215\256\345\272\223\346\212\200\346\234\257/Mysql\345\237\272\347\241\200\347\237\245\350\257\206.md" +++ /dev/null @@ -1,2021 +0,0 @@ -# 本章节数据库技术按照导图展开,如下: - -
- 数据库学习导图 -
- -# 数据库基础原理 -学习来源:[数据库](https://www.bilibili.com/video/BV1Vt411z7wy?p=19) -数据库主要分为:关系型数据库和非关系型数据库。 -关系型数据库的代表有:`MySQL`,非关系型数据库代表有:`MongonDB` - -## cmd命令行登录和退出MySQL服务器 - -```markdown -# 登录MySQL -$ mysql -u root -p12345612 - -# 退出MySQL数据库服务器 -exit; -# 输入回车即可 -``` - -## 基本语法 - -```mysql --- 显示所有数据库 -show databases; - --- 创建数据库 -CREATE DATABASE test; - --- 删除数据库 -drop database test; - --- 切换数据库 -use test; - --- 显示数据库中的所有表 -show tables; - --- 创建数据表 -CREATE TABLE pet ( - name VARCHAR(20), - owner VARCHAR(20), - species VARCHAR(20), - sex CHAR(1), - birth DATE, - death DATE -); - --- 查看数据表结构 --- describe pet; -desc pet; - --- 查询表 -SELECT * from pet; - --- 插入数据方式一 -INSERT INTO pet VALUES ('puffball', 'Diane', 'hamster', 'f', '1990-03-30', NULL); - --- 插入数据方式二 -INSERT INTO pet(name,owner) VALUES ("nkhkah","jgajjhj"); - --- 修改数据 -UPDATE pet SET name = 'squirrel' where owner = 'Diane'; - --- 删除数据 -DELETE FROM pet where name = 'squirrel'; - --- 删除表 -DROP TABLE myorder; -``` -## 建表约束 - -### 主键约束(PRIMARY KEY) - -```mysql --- 主键约束(PRIMARY KEY) --- 约束意义:能够唯一确定一张表的一条记录,通过对某个字段添加约束,可以使该字段不重复不为空。类似于人的身份证号,能够唯一确定。 -CREATE TABLE user ( - id INT PRIMARY KEY, - name VARCHAR(20) -); - --- 联合主键(PRIMARY KEY) --- 联合主键中的每个主键都不能为空,规定只需要联合字段加起来不重复即可。比如user1(1,"shadow","12345")和user2(1,"liyuanbo","12345")不重复,即不会报错。 -CREATE TABLE user ( - id INT, - name VARCHAR(20), - password VARCHAR(20), - PRIMARY KEY(id, name) -); - --- 添加主键约束 --- 如果忘记设置主键,还可以通过SQL语句设置(两种方式): -ALTER TABLE user ADD PRIMARY KEY(id); -ALTER TABLE user MODIFY id INT PRIMARY KEY; - --- 删除主键 -ALTER TABLE user drop PRIMARY KEY; - -``` - -### 自增约束(AUTO_INCREMENT) - -```mysql --- 自增约束(AUTO_INCREMENT) --- 约束意义:自增约束的主键由系统自动递增分配。比如给id自增,插入时不需要给id赋值,会自增。 -CREATE TABLE user ( - id INT PRIMARY KEY AUTO_INCREMENT, - name VARCHAR(20) -); -``` - -### 唯一约束(UNIQUE) - -```mysql --- 建表时创建唯一约束 --- 约束意义:约束修饰字段的值不可以重复,可以为空,即唯一 独一无二。 -CREATE TABLE user ( - id INT, - name VARCHAR(20), - UNIQUE(name) -); - --- 添加唯一主键 --- 如果建表时没有设置唯一建,还可以通过SQL语句设置(两种方式): -ALTER TABLE user ADD UNIQUE(name); -ALTER TABLE user MODIFY name VARCHAR(20) UNIQUE; - --- 删除唯一主键 -ALTER TABLE user DROP INDEX name; -``` - -### 非空约束(NOT NULL) - -```mysql --- 建表时添加非空约束 --- 约束意义:约束某个字段不能为空 -CREATE TABLE user ( - id INT, - name VARCHAR(20) NOT NULL -); - --- 移除非空约束 -ALTER TABLE user MODIFY name VARCHAR(20); -``` - -### 默认约束(DEFAULT) - -```mysql --- 建表时添加默认约束 --- 约束意义:约束某个字段的默认值。当你不给该字段赋值时,会默认赋予默认值。 -CREATE TABLE user2 ( - id INT, - name VARCHAR(20), - age INT DEFAULT 10 -); - --- 移除非空约束 -ALTER TABLE user MODIFY age INT; -``` - -### 外键约束(FOREIGN KEY) - -```mysql --- 主要关联多个表,比如父表和子表或主表和副表。如下的班级表和学生表,学生表的class_id必须来自班级表的id。 --- 约束意义:关联其他外表 - --- 班级 -CREATE TABLE classes ( - id INT PRIMARY KEY, - name VARCHAR(20) -); - --- 学生表 -CREATE TABLE students ( - id INT PRIMARY KEY, - name VARCHAR(20), - -- 这里的 class_id 要和 classes 中的 id 字段相关联 - class_id INT, - -- 表示 class_id 的值必须来自于 classes 中的 id 字段值 - FOREIGN KEY(class_id) REFERENCES classes(id) -); - --- 1. 主表(父表)classes 中没有的数据值,在副表(子表)students 中,是不可以使用的; --- 2. 主表中的记录被副表引用时,主表不可以被删除。 -``` - -## 数据库的三大设计范式 - -### 第一范式(1NF) - -数据库中的所有字段都是`不可分割`的原子值 - -字段值可以拆分的就不满足第一范式 -```mysql -create table student( - id int primary key, - name varchar(20), - address varchar(30) -); - -insert into student values (1,"","中国江苏省南京市玄武区南京街道"); --- 对于这种address字段可以拆分,所以不满足第一范式。 - -create table student( - id int primary key, - name varchar(20), - country varchar(10), - city varchar(10), - detail varchar(20) -); - --- 假设detail字段不能拆分,则满足第一范式 -``` - -### 第二范式(2NF) - -在`满足第一范式`的前提下,其他列都必须完全依赖于主键列。如果出现不完全依赖,只可能发生在联合主键的情况下: - -```mysql --- 订单表 -CREATE TABLE myorder ( - product_id INT, - customer_id INT, - product_name VARCHAR(20), - customer_name VARCHAR(20), - PRIMARY KEY (product_id, customer_id) -); -``` - -因为此表是联合主键`PRIMARY KEY (product_id, customer_id)` 而product_name只和product_id相关,customer_name只和customer_id相关,即部分依赖。而其他字段(`product_name`和`customer_name`)不完全依赖主键。 - -所以不满足第二范式。 - -若将其拆分如下: - -```mysql -CREATE TABLE myorder ( - order_id INT PRIMARY KEY, - product_id INT, - customer_id INT -); - -CREATE TABLE product ( - id INT PRIMARY KEY, - name VARCHAR(20) -); - -CREATE TABLE customer ( - id INT PRIMARY KEY, - name VARCHAR(20) -); -``` - -拆分之后,`myorder` 表中的 `product_id` 和 `customer_id` 完全依赖于 `order_id` 主键,而 `product` 和 `customer` 表中的其他字段又完全依赖于主键。满足了第二范式的设计! - -### 第三范式(3NF) - -在满足第二范式的前提下,除了主键列之外,其他列之间不能有传递依赖关系。 - -```mysql -CREATE TABLE myorder ( - order_id INT PRIMARY KEY, - product_id INT, - customer_id INT, - customer_phone VARCHAR(15) -); -``` -在上述的订单表中,`customer_phone`依赖于`order_id`,也有可能依赖于`customer_id`。就是`customer_id`可以通过`order_id`找到,`customer_phone`需要通过`customer_id`找到,所以依赖关系产生冗余。 - -若将其拆分: - -```mysql -CREATE TABLE myorder ( - order_id INT PRIMARY KEY, - product_id INT, - customer_id INT -); - -CREATE TABLE customer ( - id INT PRIMARY KEY, - name VARCHAR(20), - phone VARCHAR(15) -); -``` - -修改后就不存在其他列之间的传递依赖关系,其他列都只依赖于主键列,满足了第三范式的设计! - -## 查询练习 - -### 准备数据 - -```mysql --- 创建数据库 -CREATE DATABASE select_test; --- 切换数据库 -USE select_test; - --- 创建学生表 -CREATE TABLE student ( - sno VARCHAR(20) PRIMARY KEY, - name VARCHAR(20) NOT NULL, - sex VARCHAR(10) NOT NULL, - birthday DATE, -- 生日 - class VARCHAR(20) -- 所在班级 -); - --- 创建教师表 -CREATE TABLE teacher ( - tno VARCHAR(20) PRIMARY KEY, - name VARCHAR(20) NOT NULL, - sex VARCHAR(10) NOT NULL, - birthday DATE, - profession VARCHAR(20) NOT NULL, -- 职称 - department VARCHAR(20) NOT NULL -- 部门 -); - --- 创建课程表 -CREATE TABLE course ( - cno VARCHAR(20) PRIMARY KEY, - name VARCHAR(20) NOT NULL, - tno VARCHAR(20) NOT NULL,-- 教师编号 - -- 表示该 tno 来自于 teacher 表中的 no 字段值 - FOREIGN KEY(tno) REFERENCES teacher(tno) -); - --- 成绩表 -CREATE TABLE score ( - sno VARCHAR(20) NOT NULL, -- 学生编号 - cno VARCHAR(20) NOT NULL, -- 课程号 - degree DECIMAL, -- 成绩 - -- 表示该 s_no, c_no 分别来自于 student, course 表中的 no 字段值 - FOREIGN KEY(sno) REFERENCES student(sno), - FOREIGN KEY(cno) REFERENCES course(cno), - -- 设置 s_no, c_no 为联合主键 - PRIMARY KEY(sno,cno) -); - --- 查看所有表 -SHOW TABLES; - --- 添加学生表数据 -INSERT INTO student VALUES('101', '曾华', '男', '1977-09-01', '95033'); -INSERT INTO student VALUES('102', '匡明', '男', '1975-10-02', '95031'); -INSERT INTO student VALUES('103', '王丽', '女', '1976-01-23', '95033'); -INSERT INTO student VALUES('104', '李军', '男', '1976-02-20', '95033'); -INSERT INTO student VALUES('105', '王芳', '女', '1975-02-10', '95031'); -INSERT INTO student VALUES('106', '陆军', '男', '1974-06-03', '95031'); -INSERT INTO student VALUES('107', '王尼玛', '男', '1976-02-20', '95033'); -INSERT INTO student VALUES('108', '张全蛋', '男', '1975-02-10', '95031'); -INSERT INTO student VALUES('109', '赵铁柱', '男', '1974-06-03', '95031'); - --- 添加教师表数据 -INSERT INTO teacher VALUES('804', '李诚', '男', '1958-12-02', '副教授', '计算机系'); -INSERT INTO teacher VALUES('856', '张旭', '男', '1969-03-12', '讲师', '电子工程系'); -INSERT INTO teacher VALUES('825', '王萍', '女', '1972-05-05', '助教', '计算机系'); -INSERT INTO teacher VALUES('831', '刘冰', '女', '1977-08-14', '助教', '电子工程系'); - --- 添加课程表数据 -INSERT INTO course VALUES('3-105', '计算机导论', '825'); -INSERT INTO course VALUES('3-245', '操作系统', '804'); -INSERT INTO course VALUES('6-166', '数字电路', '856'); -INSERT INTO course VALUES('9-888', '高等数学', '831'); - --- 添加添加成绩表数据 -INSERT INTO score VALUES('103', '3-105', '92'); -INSERT INTO score VALUES('103', '3-245', '86'); -INSERT INTO score VALUES('103', '6-166', '85'); -INSERT INTO score VALUES('105', '3-105', '88'); -INSERT INTO score VALUES('105', '3-245', '75'); -INSERT INTO score VALUES('105', '6-166', '79'); -INSERT INTO score VALUES('109', '3-105', '76'); -INSERT INTO score VALUES('109', '3-245', '68'); -INSERT INTO score VALUES('109', '6-166', '81'); - --- 查看表结构 -SELECT * FROM course; -SELECT * FROM score; -SELECT * FROM student; -SELECT * FROM teacher; -``` - -### 1 到 10 - -```mysql --- 查询 student 表的所有行 -SELECT * FROM student; - --- 查询 student 表中的 name、sex 和 class 字段的所有行 -SELECT name,sex,class FROM student; - --- 查询 teacher 表中不重复的 department 列 --- department: 去重查询 -SELECT DISTINCT department FROM teacher; - --- 查询 score 表中成绩在60-80之间的所有行(区间查询和运算符查询) --- BETWEEN xx AND xx: 查询区间, AND 表示 "并且" -SELECT * FROM score WHERE degree BETWEEN 60 AND 80; -SELECT * FROM score WHERE degree > 60 AND degree < 80; - --- 查询 score 表中成绩为 85, 86 或 88 的行 --- IN: 查询规定中的多个值 -SELECT * FROM score WHERE degree IN (85, 86, 88); - --- 查询 student 表中 '95031' 班或性别为 '女' 的所有行 --- or: 表示或者关系 -SELECT * FROM student WHERE class = '95031' or sex = '女'; - --- 以 class 降序的方式查询 student 表的所有行 --- DESC: 降序,从高到低 --- ASC(默认): 升序,从低到高 -SELECT * FROM student ORDER BY class DESC; -SELECT * FROM student ORDER BY class ASC; - --- 以 cno 升序、degree 降序查询 score 表的所有行 -SELECT * FROM score ORDER BY cno ASC, degree DESC; - --- 查询 "95031" 班的学生人数 --- COUNT: 统计 -SELECT COUNT(*) FROM student WHERE class = '95031'; - --- 查询 score 表中的最高分的学生学号和课程编号(子查询或排序查询)。 --- (SELECT MAX(degree) FROM score): 子查询,算出最高分 -SELECT sno, cno FROM score WHERE degree = (SELECT MAX(degree) FROM score); - --- 排序查询 --- LIMIT r, n: 表示从第r行开始,查询n条数据 -SELECT s_no, c_no, degree FROM score ORDER BY degree DESC LIMIT 0, 1; -``` - -### 分组计算平均成绩 - -**查询每门课的平均成绩。** - -```mysql --- AVG: 平均值 -SELECT AVG(degree) FROM score WHERE c_no = '3-105'; -SELECT AVG(degree) FROM score WHERE c_no = '3-245'; -SELECT AVG(degree) FROM score WHERE c_no = '6-166'; - --- GROUP BY: 分组查询 -SELECT c_no, AVG(degree) FROM score GROUP BY c_no; -``` - -### 分组条件与模糊查询 - -**查询 `score` 表中至少有 2 名学生选修,并以 3 开头的课程的平均分数。** - -```mysql -SELECT * FROM score; --- c_no 课程编号 -+------+-------+--------+ -| sno | cno | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -| 103 | 3-245 | 86 | -| 103 | 6-166 | 85 | -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -分析表发现,至少有 2 名学生选修的课程是 `3-105` 、`3-245` 、`6-166` ,以 3 开头的课程是 `3-105` 、`3-245` 。也就是说,我们要查询所有 `3-105` 和 `3-245` 的 `degree` 平均分。 - -```mysql --- 首先把 c_no, AVG(degree) 通过分组查询出来 -SELECT c_no, AVG(degree) FROM score GROUP BY c_no -+-------+-------------+ -| c_no | AVG(degree) | -+-------+-------------+ -| 3-105 | 85.3333 | -| 3-245 | 76.3333 | -| 6-166 | 81.6667 | -+-------+-------------+ - --- 再查询出至少有 2 名学生选修的课程 --- HAVING: 表示持有 -HAVING COUNT(c_no) >= 2 - --- 并且是以 3 开头的课程 --- LIKE 表示模糊查询,"%" 是一个通配符,匹配 "3" 后面的任意字符。 -AND c_no LIKE '3%'; - --- 把前面的SQL语句拼接起来, --- 后面加上一个 COUNT(*),表示将每个分组的个数也查询出来。 -SELECT c_no, AVG(degree), COUNT(*) FROM score GROUP BY c_no -HAVING COUNT(c_no) >= 2 AND c_no LIKE '3%'; -+-------+-------------+----------+ -| cno | AVG(degree) | COUNT(*) | -+-------+-------------+----------+ -| 3-105 | 85.3333 | 3 | -| 3-245 | 76.3333 | 3 | -+-------+-------------+----------+ -``` - -### 多表查询 - 1 - -**查询所有学生的 `name`,以及该学生在 `score` 表中对应的 `c_no` 和 `degree` 。** - -```mysql -SELECT no, name FROM student; -+-----+-----------+ -| no | name | -+-----+-----------+ -| 101 | 曾华 | -| 102 | 匡明 | -| 103 | 王丽 | -| 104 | 李军 | -| 105 | 王芳 | -| 106 | 陆军 | -| 107 | 王尼玛 | -| 108 | 张全蛋 | -| 109 | 赵铁柱 | -+-----+-----------+ - -SELECT sno, cno, degree FROM score; -+------+-------+--------+ -| sno | cno | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -| 103 | 3-245 | 86 | -| 103 | 6-166 | 85 | -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -通过分析可以发现,只要把 `score` 表中的 `sno` 字段值替换成 `student` 表中对应的 `name` 字段值就可以了,如何做呢? - -```mysql --- FROM...: 表示从 student, score 表中查询 --- WHERE 的条件表示为,只有在 student.no 和 score.s_no 相等时才显示出来。 -SELECT name, cno, degree FROM student,score -WHERE student.no = score.s_no; -+-----------+-------+--------+ -| name | c_no | degree | -+-----------+-------+--------+ -| 王丽 | 3-105 | 92 | -| 王丽 | 3-245 | 86 | -| 王丽 | 6-166 | 85 | -| 王芳 | 3-105 | 88 | -| 王芳 | 3-245 | 75 | -| 王芳 | 6-166 | 79 | -| 赵铁柱 | 3-105 | 76 | -| 赵铁柱 | 3-245 | 68 | -| 赵铁柱 | 6-166 | 81 | -+-----------+-------+--------+ -``` - -### 多表查询 - 2 - -**查询所有学生的 `no` 、课程名称 ( `course` 表中的 `name` ) 和成绩 ( `score` 表中的 `degree` ) 列。** - -只有 `score` 关联学生的 `no` ,因此只要查询 `score` 表,就能找出所有和学生相关的 `no` 和 `degree` : - -```mysql -SELECT s_no, c_no, degree FROM score; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -| 103 | 3-245 | 86 | -| 103 | 6-166 | 85 | -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -然后查询 `course` 表: - -```mysql -+-------+-----------------+ -| no | name | -+-------+-----------------+ -| 3-105 | 计算机导论 | -| 3-245 | 操作系统 | -| 6-166 | 数字电路 | -| 9-888 | 高等数学 | -+-------+-----------------+ -``` - -只要把 `score` 表中的 `c_no` 替换成 `course` 表中对应的 `name` 字段值就可以了。 - -```mysql --- 增加一个查询字段 name,分别从 score、course 这两个表中查询。 --- as 表示取一个该字段的别名。 -SELECT s_no, name as c_name, degree FROM score, course -WHERE score.c_no = course.no; -+------+-----------------+--------+ -| s_no | c_name | degree | -+------+-----------------+--------+ -| 103 | 计算机导论 | 92 | -| 105 | 计算机导论 | 88 | -| 109 | 计算机导论 | 76 | -| 103 | 操作系统 | 86 | -| 105 | 操作系统 | 75 | -| 109 | 操作系统 | 68 | -| 103 | 数字电路 | 85 | -| 105 | 数字电路 | 79 | -| 109 | 数字电路 | 81 | -+------+-----------------+--------+ -``` - -### 三表关联查询 - -**查询所有学生的 `name` 、课程名 ( `course` 表中的 `name` ) 和 `degree` 。** - -只有 `score` 表中关联学生的学号和课堂号,我们只要围绕着 `score` 这张表查询就好了。 - -```mysql -SELECT * FROM score; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -| 103 | 3-245 | 86 | -| 103 | 6-166 | 85 | -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -只要把 `s_no` 和 `c_no` 替换成 `student` 和 `srouse` 表中对应的 `name` 字段值就好了。 - -首先把 `s_no` 替换成 `student` 表中的 `name` 字段: - -```mysql -SELECT name, c_no, degree FROM student, score WHERE student.no = score.s_no; -+-----------+-------+--------+ -| name | c_no | degree | -+-----------+-------+--------+ -| 王丽 | 3-105 | 92 | -| 王丽 | 3-245 | 86 | -| 王丽 | 6-166 | 85 | -| 王芳 | 3-105 | 88 | -| 王芳 | 3-245 | 75 | -| 王芳 | 6-166 | 79 | -| 赵铁柱 | 3-105 | 76 | -| 赵铁柱 | 3-245 | 68 | -| 赵铁柱 | 6-166 | 81 | -+-----------+-------+--------+ -``` - -再把 `c_no` 替换成 `course` 表中的 `name` 字段: - -```mysql --- 课程表 -SELECT no, name FROM course; -+-------+-----------------+ -| no | name | -+-------+-----------------+ -| 3-105 | 计算机导论 | -| 3-245 | 操作系统 | -| 6-166 | 数字电路 | -| 9-888 | 高等数学 | -+-------+-----------------+ - --- 由于字段名存在重复,使用 "表名.字段名 as 别名" 代替。 -SELECT student.name as s_name, course.name as c_name, degree -FROM student, score, course -WHERE student.NO = score.s_no -AND score.c_no = course.no; -``` - -### 子查询加分组求平均分 - -**查询 `95031` 班学生每门课程的平均成绩。** - -在 `score` 表中根据 `student` 表的学生编号筛选出学生的课堂号和成绩: - -```mysql --- IN (..): 将筛选出的学生号当做 s_no 的条件查询 -SELECT s_no, c_no, degree FROM score -WHERE s_no IN (SELECT no FROM student WHERE class = '95031'); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -这时只要将 `c_no` 分组一下就能得出 `95031` 班学生每门课的平均成绩: - -```mysql -SELECT c_no, AVG(degree) FROM score -WHERE s_no IN (SELECT no FROM student WHERE class = '95031') -GROUP BY c_no; -+-------+-------------+ -| c_no | AVG(degree) | -+-------+-------------+ -| 3-105 | 82.0000 | -| 3-245 | 71.5000 | -| 6-166 | 80.0000 | -+-------+-------------+ -``` - -### 子查询 - 1 - -**查询在 `3-105` 课程中,所有成绩高于 `109` 号同学的记录。** - -首先筛选出课堂号为 `3-105` ,在找出所有成绩高于 `109` 号同学的的行。 - -```mysql -SELECT * FROM score -WHERE c_no = '3-105' -AND degree > (SELECT degree FROM score WHERE s_no = '109' AND c_no = '3-105'); -``` - -### 子查询 - 2 - -**查询所有成绩高于 `109` 号同学的 `3-105` 课程成绩记录。** - -```mysql --- 不限制课程号,只要成绩大于109号同学的3-105课程成绩就可以。 -SELECT * FROM score -WHERE degree > (SELECT degree FROM score WHERE s_no = '109' AND c_no = '3-105'); -``` - -### YEAR 函数与带 IN 关键字查询 - -**查询所有和 `101` 、`108` 号学生同年出生的 `no` 、`name` 、`birthday` 列。** - -```mysql --- YEAR(..): 取出日期中的年份 -SELECT no, name, birthday FROM student -WHERE YEAR(birthday) IN (SELECT YEAR(birthday) FROM student WHERE no IN (101, 108)); -``` - -### 多层嵌套子查询 - -**查询 `'张旭'` 教师任课的学生成绩表。** - -首先找到教师编号: - -```mysql -SELECT NO FROM teacher WHERE NAME = '张旭' -``` - -通过 `sourse` 表找到该教师课程号: - -```mysql -SELECT NO FROM course WHERE t_no = ( SELECT NO FROM teacher WHERE NAME = '张旭' ); -``` - -通过筛选出的课程号查询成绩表: - -```mysql -SELECT * FROM score WHERE c_no = ( - SELECT no FROM course WHERE t_no = ( - SELECT no FROM teacher WHERE NAME = '张旭' - ) -); -``` - -### 多表查询 - -**查询某选修课程多于5个同学的教师姓名。** - -首先在 `teacher` 表中,根据 `no` 字段来判断该教师的同一门课程是否有至少5名学员选修: - -```mysql --- 查询 teacher 表 -SELECT no, name FROM teacher; -+-----+--------+ -| no | name | -+-----+--------+ -| 804 | 李诚 | -| 825 | 王萍 | -| 831 | 刘冰 | -| 856 | 张旭 | -+-----+--------+ - -SELECT name FROM teacher WHERE no IN ( - -- 在这里找到对应的条件 -); -``` - -查看和教师编号有有关的表的信息: - -```mysql -SELECT * FROM course; --- t_no: 教师编号 -+-------+-----------------+------+ -| no | name | t_no | -+-------+-----------------+------+ -| 3-105 | 计算机导论 | 825 | -| 3-245 | 操作系统 | 804 | -| 6-166 | 数字电路 | 856 | -| 9-888 | 高等数学 | 831 | -+-------+-----------------+------+ -``` - -我们已经找到和教师编号有关的字段就在 `course` 表中,但是还无法知道哪门课程至少有5名学生选修,所以还需要根据 `score` 表来查询: - -```mysql --- 在此之前向 score 插入一些数据,以便丰富查询条件。 -INSERT INTO score VALUES ('101', '3-105', '90'); -INSERT INTO score VALUES ('102', '3-105', '91'); -INSERT INTO score VALUES ('104', '3-105', '89'); - --- 查询 score 表 -SELECT * FROM score; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 101 | 3-105 | 90 | -| 102 | 3-105 | 91 | -| 103 | 3-105 | 92 | -| 103 | 3-245 | 86 | -| 103 | 6-166 | 85 | -| 104 | 3-105 | 89 | -| 105 | 3-105 | 88 | -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ - --- 在 score 表中将 c_no 作为分组,并且限制 c_no 持有至少 5 条数据。 -SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5; -+-------+ -| c_no | -+-------+ -| 3-105 | -+-------+ -``` - -根据筛选出来的课程号,找出在某课程中,拥有至少5名学员的教师编号: - -```mysql -SELECT t_no FROM course WHERE no IN ( - SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5 -); -+------+ -| t_no | -+------+ -| 825 | -+------+ -``` - -在 `teacher` 表中,根据筛选出来的教师编号找到教师姓名: - -```mysql -SELECT name FROM teacher WHERE no IN ( - -- 最终条件 - SELECT t_no FROM course WHERE no IN ( - SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5 - ) -); -``` - -### 子查询 - 3 - -**查询 “计算机系” 课程的成绩表。** - -思路是,先找出 `course` 表中所有 `计算机系` 课程的编号,然后根据这个编号查询 `score` 表。 - -```mysql --- 通过 teacher 表查询所有 `计算机系` 的教师编号 -SELECT no, name, department FROM teacher WHERE department = '计算机系' -+-----+--------+--------------+ -| no | name | department | -+-----+--------+--------------+ -| 804 | 李诚 | 计算机系 | -| 825 | 王萍 | 计算机系 | -+-----+--------+--------------+ - --- 通过 course 表查询该教师的课程编号 -SELECT no FROM course WHERE t_no IN ( - SELECT no FROM teacher WHERE department = '计算机系' -); -+-------+ -| no | -+-------+ -| 3-245 | -| 3-105 | -+-------+ - --- 根据筛选出来的课程号查询成绩表 -SELECT * FROM score WHERE c_no IN ( - SELECT no FROM course WHERE t_no IN ( - SELECT no FROM teacher WHERE department = '计算机系' - ) -); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-245 | 86 | -| 105 | 3-245 | 75 | -| 109 | 3-245 | 68 | -| 101 | 3-105 | 90 | -| 102 | 3-105 | 91 | -| 103 | 3-105 | 92 | -| 104 | 3-105 | 89 | -| 105 | 3-105 | 88 | -| 109 | 3-105 | 76 | -+------+-------+--------+ -``` - -### UNION 和 NOTIN 的使用 - -**查询 `计算机系` 与 `电子工程系` 中的不同职称的教师。** - -```mysql --- NOT: 代表逻辑非 -SELECT * FROM teacher WHERE department = '计算机系' AND profession NOT IN ( - SELECT profession FROM teacher WHERE department = '电子工程系' -) --- 合并两个集 -UNION -SELECT * FROM teacher WHERE department = '电子工程系' AND profession NOT IN ( - SELECT profession FROM teacher WHERE department = '计算机系' -); -``` - -### ANY 表示至少一个 - DESC ( 降序 ) - -**查询课程 `3-105` 且成绩 至少 高于 `3-245` 的 `score` 表。** - -```mysql -SELECT * FROM score WHERE c_no = '3-105'; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 101 | 3-105 | 90 | -| 102 | 3-105 | 91 | -| 103 | 3-105 | 92 | -| 104 | 3-105 | 89 | -| 105 | 3-105 | 88 | -| 109 | 3-105 | 76 | -+------+-------+--------+ - -SELECT * FROM score WHERE c_no = '3-245'; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-245 | 86 | -| 105 | 3-245 | 75 | -| 109 | 3-245 | 68 | -+------+-------+--------+ - --- ANY: 符合SQL语句中的任意条件。 --- 也就是说,在 3-105 成绩中,只要有一个大于从 3-245 筛选出来的任意行就符合条件, --- 最后根据降序查询结果。 -SELECT * FROM score WHERE c_no = '3-105' AND degree > ANY( - SELECT degree FROM score WHERE c_no = '3-245' -) ORDER BY degree DESC; -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -| 102 | 3-105 | 91 | -| 101 | 3-105 | 90 | -| 104 | 3-105 | 89 | -| 105 | 3-105 | 88 | -| 109 | 3-105 | 76 | -+------+-------+--------+ -``` - -### 表示所有的 ALL - -**查询课程 `3-105` 且成绩高于 `3-245` 的 `score` 表。** - -```mysql --- 只需对上一道题稍作修改。 --- ALL: 符合SQL语句中的所有条件。 --- 也就是说,在 3-105 每一行成绩中,都要大于从 3-245 筛选出来全部行才算符合条件。 -SELECT * FROM score WHERE c_no = '3-105' AND degree > ALL( - SELECT degree FROM score WHERE c_no = '3-245' -); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 101 | 3-105 | 90 | -| 102 | 3-105 | 91 | -| 103 | 3-105 | 92 | -| 104 | 3-105 | 89 | -| 105 | 3-105 | 88 | -+------+-------+--------+ -``` - -### 复制表的数据作为条件查询 - -**查询某课程成绩比该课程平均成绩低的 `score` 表。** - -```mysql --- 查询平均分 -SELECT c_no, AVG(degree) FROM score GROUP BY c_no; -+-------+-------------+ -| c_no | AVG(degree) | -+-------+-------------+ -| 3-105 | 87.6667 | -| 3-245 | 76.3333 | -| 6-166 | 81.6667 | -+-------+-------------+ - --- 查询 score 表 -SELECT degree FROM score; -+--------+ -| degree | -+--------+ -| 90 | -| 91 | -| 92 | -| 86 | -| 85 | -| 89 | -| 88 | -| 75 | -| 79 | -| 76 | -| 68 | -| 81 | -+--------+ - --- 将表 b 作用于表 a 中查询数据 --- score a (b): 将表声明为 a (b), --- 如此就能用 a.c_no = b.c_no 作为条件执行查询了。 -SELECT * FROM score a WHERE degree < ( - (SELECT AVG(degree) FROM score b WHERE a.c_no = b.c_no) -); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 105 | 3-245 | 75 | -| 105 | 6-166 | 79 | -| 109 | 3-105 | 76 | -| 109 | 3-245 | 68 | -| 109 | 6-166 | 81 | -+------+-------+--------+ -``` - -### 子查询 - 4 - -**查询所有任课 ( 在 `course` 表里有课程 ) 教师的 `name` 和 `department`** 。 - -```mysql -SELECT name, department FROM teacher WHERE no IN (SELECT t_no FROM course); -+--------+-----------------+ -| name | department | -+--------+-----------------+ -| 李诚 | 计算机系 | -| 王萍 | 计算机系 | -| 刘冰 | 电子工程系 | -| 张旭 | 电子工程系 | -+--------+-----------------+ -``` - -### 条件加组筛选 - -**查询 `student` 表中至少有 2 名男生的 `class` 。** - -```mysql --- 查看学生表信息 -SELECT * FROM student; -+-----+-----------+-----+------------+-------+ -| no | name | sex | birthday | class | -+-----+-----------+-----+------------+-------+ -| 101 | 曾华 | 男 | 1977-09-01 | 95033 | -| 102 | 匡明 | 男 | 1975-10-02 | 95031 | -| 103 | 王丽 | 女 | 1976-01-23 | 95033 | -| 104 | 李军 | 男 | 1976-02-20 | 95033 | -| 105 | 王芳 | 女 | 1975-02-10 | 95031 | -| 106 | 陆军 | 男 | 1974-06-03 | 95031 | -| 107 | 王尼玛 | 男 | 1976-02-20 | 95033 | -| 108 | 张全蛋 | 男 | 1975-02-10 | 95031 | -| 109 | 赵铁柱 | 男 | 1974-06-03 | 95031 | -| 110 | 张飞 | 男 | 1974-06-03 | 95038 | -+-----+-----------+-----+------------+-------+ - --- 只查询性别为男,然后按 class 分组,并限制 class 行大于 1。 -SELECT class FROM student WHERE sex = '男' GROUP BY class HAVING COUNT(*) > 1; -+-------+ -| class | -+-------+ -| 95033 | -| 95031 | -+-------+ -``` - -### NOTLIKE 模糊查询取反 - -**查询 `student` 表中不姓 "王" 的同学记录。** - -```mysql --- NOT: 取反 --- LIKE: 模糊查询 -mysql> SELECT * FROM student WHERE name NOT LIKE '王%'; -+-----+-----------+-----+------------+-------+ -| no | name | sex | birthday | class | -+-----+-----------+-----+------------+-------+ -| 101 | 曾华 | 男 | 1977-09-01 | 95033 | -| 102 | 匡明 | 男 | 1975-10-02 | 95031 | -| 104 | 李军 | 男 | 1976-02-20 | 95033 | -| 106 | 陆军 | 男 | 1974-06-03 | 95031 | -| 108 | 张全蛋 | 男 | 1975-02-10 | 95031 | -| 109 | 赵铁柱 | 男 | 1974-06-03 | 95031 | -| 110 | 张飞 | 男 | 1974-06-03 | 95038 | -+-----+-----------+-----+------------+-------+ -``` - -### YEAR 与 NOW 函数 - -**查询 `student` 表中每个学生的姓名和年龄。** - -```mysql --- 使用函数 YEAR(NOW()) 计算出当前年份,减去出生年份后得出年龄。 -SELECT name, YEAR(NOW()) - YEAR(birthday) as age FROM student; -+-----------+------+ -| name | age | -+-----------+------+ -| 曾华 | 42 | -| 匡明 | 44 | -| 王丽 | 43 | -| 李军 | 43 | -| 王芳 | 44 | -| 陆军 | 45 | -| 王尼玛 | 43 | -| 张全蛋 | 44 | -| 赵铁柱 | 45 | -| 张飞 | 45 | -+-----------+------+ -``` - -### MAX 与 MIN 函数 - -**查询 `student` 表中最大和最小的 `birthday` 值。** - -```mysql -SELECT MAX(birthday), MIN(birthday) FROM student; -+---------------+---------------+ -| MAX(birthday) | MIN(birthday) | -+---------------+---------------+ -| 1977-09-01 | 1974-06-03 | -+---------------+---------------+ -``` - -### 多段排序 - -**以 `class` 和 `birthday` 从大到小的顺序查询 `student` 表。** - -```mysql -SELECT * FROM student ORDER BY class DESC, birthday; -+-----+-----------+-----+------------+-------+ -| no | name | sex | birthday | class | -+-----+-----------+-----+------------+-------+ -| 110 | 张飞 | 男 | 1974-06-03 | 95038 | -| 103 | 王丽 | 女 | 1976-01-23 | 95033 | -| 104 | 李军 | 男 | 1976-02-20 | 95033 | -| 107 | 王尼玛 | 男 | 1976-02-20 | 95033 | -| 101 | 曾华 | 男 | 1977-09-01 | 95033 | -| 106 | 陆军 | 男 | 1974-06-03 | 95031 | -| 109 | 赵铁柱 | 男 | 1974-06-03 | 95031 | -| 105 | 王芳 | 女 | 1975-02-10 | 95031 | -| 108 | 张全蛋 | 男 | 1975-02-10 | 95031 | -| 102 | 匡明 | 男 | 1975-10-02 | 95031 | -+-----+-----------+-----+------------+-------+ -``` - -### 子查询 - 5 - -**查询 "男" 教师及其所上的课程。** - -```mysql -SELECT * FROM course WHERE t_no in (SELECT no FROM teacher WHERE sex = '男'); -+-------+--------------+------+ -| no | name | t_no | -+-------+--------------+------+ -| 3-245 | 操作系统 | 804 | -| 6-166 | 数字电路 | 856 | -+-------+--------------+------+ -``` - -### MAX 函数与子查询 - -**查询最高分同学的 `score` 表。** - -```mysql --- 找出最高成绩(该查询只能有一个结果) -SELECT MAX(degree) FROM score; - --- 根据上面的条件筛选出所有最高成绩表, --- 该查询可能有多个结果,假设 degree 值多次符合条件。 -SELECT * FROM score WHERE degree = (SELECT MAX(degree) FROM score); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 103 | 3-105 | 92 | -+------+-------+--------+ -``` - -### 子查询 - 6 - -**查询和 "李军" 同性别的所有同学 `name` 。** - -```mysql --- 首先将李军的性别作为条件取出来 -SELECT sex FROM student WHERE name = '李军'; -+-----+ -| sex | -+-----+ -| 男 | -+-----+ - --- 根据性别查询 name 和 sex -SELECT name, sex FROM student WHERE sex = ( - SELECT sex FROM student WHERE name = '李军' -); -+-----------+-----+ -| name | sex | -+-----------+-----+ -| 曾华 | 男 | -| 匡明 | 男 | -| 李军 | 男 | -| 陆军 | 男 | -| 王尼玛 | 男 | -| 张全蛋 | 男 | -| 赵铁柱 | 男 | -| 张飞 | 男 | -+-----------+-----+ -``` - -### 子查询 - 7 - -**查询和 "李军" 同性别且同班的同学 `name` 。** - -```mysql -SELECT name, sex, class FROM student WHERE sex = ( - SELECT sex FROM student WHERE name = '李军' -) AND class = ( - SELECT class FROM student WHERE name = '李军' -); -+-----------+-----+-------+ -| name | sex | class | -+-----------+-----+-------+ -| 曾华 | 男 | 95033 | -| 李军 | 男 | 95033 | -| 王尼玛 | 男 | 95033 | -+-----------+-----+-------+ -``` - -### 子查询 - 8 - -**查询所有选修 "计算机导论" 课程的 "男" 同学成绩表。** - -需要的 "计算机导论" 和性别为 "男" 的编号可以在 `course` 和 `student` 表中找到。 - -```mysql -SELECT * FROM score WHERE c_no = ( - SELECT no FROM course WHERE name = '计算机导论' -) AND s_no IN ( - SELECT no FROM student WHERE sex = '男' -); -+------+-------+--------+ -| s_no | c_no | degree | -+------+-------+--------+ -| 101 | 3-105 | 90 | -| 102 | 3-105 | 91 | -| 104 | 3-105 | 89 | -| 109 | 3-105 | 76 | -+------+-------+--------+ -``` - -### 按等级查询 - -建立一个 `grade` 表代表学生的成绩等级,并插入数据: - -```mysql -CREATE TABLE grade ( - low INT(3), - upp INT(3), - grade char(1) -); - -INSERT INTO grade VALUES (90, 100, 'A'); -INSERT INTO grade VALUES (80, 89, 'B'); -INSERT INTO grade VALUES (70, 79, 'C'); -INSERT INTO grade VALUES (60, 69, 'D'); -INSERT INTO grade VALUES (0, 59, 'E'); - -SELECT * FROM grade; -+------+------+-------+ -| low | upp | grade | -+------+------+-------+ -| 90 | 100 | A | -| 80 | 89 | B | -| 70 | 79 | C | -| 60 | 69 | D | -| 0 | 59 | E | -+------+------+-------+ -``` - -**查询所有学生的 `s_no` 、`c_no` 和 `grade` 列。** - -思路是,使用区间 ( `BETWEEN` ) 查询,判断学生的成绩 ( `degree` ) 在 `grade` 表的 `low` 和 `upp` 之间。 - -```mysql -SELECT s_no, c_no, grade FROM score, grade -WHERE degree BETWEEN low AND upp; -+------+-------+-------+ -| s_no | c_no | grade | -+------+-------+-------+ -| 101 | 3-105 | A | -| 102 | 3-105 | A | -| 103 | 3-105 | A | -| 103 | 3-245 | B | -| 103 | 6-166 | B | -| 104 | 3-105 | B | -| 105 | 3-105 | B | -| 105 | 3-245 | C | -| 105 | 6-166 | C | -| 109 | 3-105 | C | -| 109 | 3-245 | D | -| 109 | 6-166 | B | -+------+-------+-------+ -``` - -### 连接查询 - -准备用于测试连接查询的数据: - -```mysql -CREATE DATABASE testJoin; - -CREATE TABLE person ( - id INT, - name VARCHAR(20), - cardId INT -); - -CREATE TABLE card ( - id INT, - name VARCHAR(20) -); - -INSERT INTO card VALUES (1, '饭卡'), (2, '建行卡'), (3, '农行卡'), (4, '工商卡'), (5, '邮政卡'); -SELECT * FROM card; -+------+-----------+ -| id | name | -+------+-----------+ -| 1 | 饭卡 | -| 2 | 建行卡 | -| 3 | 农行卡 | -| 4 | 工商卡 | -| 5 | 邮政卡 | -+------+-----------+ - -INSERT INTO person VALUES (1, '张三', 1), (2, '李四', 3), (3, '王五', 6); -SELECT * FROM person; -+------+--------+--------+ -| id | name | cardId | -+------+--------+--------+ -| 1 | 张三 | 1 | -| 2 | 李四 | 3 | -| 3 | 王五 | 6 | -+------+--------+--------+ -``` - -分析两张表发现,`person` 表并没有为 `cardId` 字段设置一个在 `card` 表中对应的 `id` 外键。如果设置了的话,`person` 中 `cardId` 字段值为 `6` 的行就插不进去,因为该 `cardId` 值在 `card` 表中并没有。 - -#### 内连接 - -要查询这两张表中有关系的数据,可以使用 `INNER JOIN` ( 内连接 ) 将它们连接在一起。 - -```mysql --- INNER JOIN: 表示为内连接,将两张表拼接在一起。 --- on: 表示要执行某个条件。 -SELECT * FROM person INNER JOIN card on person.cardId = card.id; -+------+--------+--------+------+-----------+ -| id | name | cardId | id | name | -+------+--------+--------+------+-----------+ -| 1 | 张三 | 1 | 1 | 饭卡 | -| 2 | 李四 | 3 | 3 | 农行卡 | -+------+--------+--------+------+-----------+ - --- 将 INNER 关键字省略掉,结果也是一样的。 --- SELECT * FROM person JOIN card on person.cardId = card.id; -``` - -> 注意:`card` 的整张表被连接到了右边。 - -#### 左外连接 - -完整显示左边的表 ( `person` ) ,右边的表如果符合条件就显示,不符合则补 `NULL` 。 - -```mysql --- LEFT JOIN 也叫做 LEFT OUTER JOIN,用这两种方式的查询结果是一样的。 -SELECT * FROM person LEFT JOIN card on person.cardId = card.id; -+------+--------+--------+------+-----------+ -| id | name | cardId | id | name | -+------+--------+--------+------+-----------+ -| 1 | 张三 | 1 | 1 | 饭卡 | -| 2 | 李四 | 3 | 3 | 农行卡 | -| 3 | 王五 | 6 | NULL | NULL | -+------+--------+--------+------+-----------+ -``` - -#### 右外链接 - -完整显示右边的表 ( `card` ) ,左边的表如果符合条件就显示,不符合则补 `NULL` 。 - -```mysql -SELECT * FROM person RIGHT JOIN card on person.cardId = card.id; -+------+--------+--------+------+-----------+ -| id | name | cardId | id | name | -+------+--------+--------+------+-----------+ -| 1 | 张三 | 1 | 1 | 饭卡 | -| 2 | 李四 | 3 | 3 | 农行卡 | -| NULL | NULL | NULL | 2 | 建行卡 | -| NULL | NULL | NULL | 4 | 工商卡 | -| NULL | NULL | NULL | 5 | 邮政卡 | -+------+--------+--------+------+-----------+ -``` - -#### 全外链接 - -完整显示两张表的全部数据。 - -```mysql --- MySQL 不支持这种语法的全外连接 --- SELECT * FROM person FULL JOIN card on person.cardId = card.id; --- 出现错误: --- ERROR 1054 (42S22): Unknown column 'person.cardId' in 'on clause' - --- MySQL全连接语法,使用 UNION 将两张表合并在一起。 -SELECT * FROM person LEFT JOIN card on person.cardId = card.id -UNION -SELECT * FROM person RIGHT JOIN card on person.cardId = card.id; -+------+--------+--------+------+-----------+ -| id | name | cardId | id | name | -+------+--------+--------+------+-----------+ -| 1 | 张三 | 1 | 1 | 饭卡 | -| 2 | 李四 | 3 | 3 | 农行卡 | -| 3 | 王五 | 6 | NULL | NULL | -| NULL | NULL | NULL | 2 | 建行卡 | -| NULL | NULL | NULL | 4 | 工商卡 | -| NULL | NULL | NULL | 5 | 邮政卡 | -+------+--------+--------+------+-----------+ -``` - -## 事务 - -在 MySQL 中,事务其实是一个最小的不可分割的工作单元。事务能够**保证一个业务的完整性**。 - -比如我们的银行转账: - -```mysql --- a -> -100 -UPDATE user set money = money - 100 WHERE name = 'a'; - --- b -> +100 -UPDATE user set money = money + 100 WHERE name = 'b'; -``` - -在实际项目中,假设只有一条 SQL 语句执行成功,而另外一条执行失败了,就会出现数据前后不一致。 - -因此,在执行多条有关联 SQL 语句时,**事务**可能会要求这些 SQL 语句要么同时执行成功,要么就都执行失败。 - -### 如何控制事务 - COMMIT / ROLLBACK - -在 MySQL 中,事务的**自动提交**状态默认是开启的。 - -```mysql --- 查询事务的自动提交状态 -SELECT @@AUTOCOMMIT; -+--------------+ -| @@AUTOCOMMIT | -+--------------+ -| 1 | -+--------------+ -``` - -**自动提交的作用**:当我们执行一条 SQL 语句的时候,其产生的效果就会立即体现出来,且不能**回滚**。 - -什么是回滚?举个例子: - -```mysql -CREATE DATABASE bank; - -USE bank; - -CREATE TABLE user ( - id INT PRIMARY KEY, - name VARCHAR(20), - money INT -); - -INSERT INTO user VALUES (1, 'a', 1000); - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -+----+------+-------+ -``` - -可以看到,在执行插入语句后数据立刻生效,原因是 MySQL 中的事务自动将它**提交**到了数据库中。那么所谓**回滚**的意思就是,撤销执行过的所有 SQL 语句,使其回滚到**最后一次提交**数据时的状态。 - -在 MySQL 中使用 `ROLLBACK` 执行回滚: - -```mysql --- 回滚到最后一次提交 -ROLLBACK; - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -+----+------+-------+ -``` - -由于所有执行过的 SQL 语句都已经被提交过了,所以数据并没有发生回滚。那如何让数据可以发生回滚? - -```mysql --- 关闭自动提交 -SET AUTOCOMMIT = 0; - --- 查询自动提交状态 -SELECT @@AUTOCOMMIT; -+--------------+ -| @@AUTOCOMMIT | -+--------------+ -| 0 | -+--------------+ -``` - -将自动提交关闭后,测试数据回滚: - -```mysql -INSERT INTO user VALUES (2, 'b', 1000); - --- 关闭 AUTOCOMMIT 后,数据的变化是在一张虚拟的临时数据表中展示, --- 发生变化的数据并没有真正插入到数据表中。 -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -| 2 | b | 1000 | -+----+------+-------+ - --- 数据表中的真实数据其实还是: -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -+----+------+-------+ - --- 由于数据还没有真正提交,可以使用回滚 -ROLLBACK; - --- 再次查询 -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -+----+------+-------+ -``` - -那如何将虚拟的数据真正提交到数据库中?使用 `COMMIT` : - -```mysql -INSERT INTO user VALUES (2, 'b', 1000); --- 手动提交数据(持久性), --- 将数据真正提交到数据库中,执行后不能再回滚提交过的数据。 -COMMIT; - --- 提交后测试回滚 -ROLLBACK; - --- 再次查询(回滚无效了) -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -| 2 | b | 1000 | -+----+------+-------+ -``` - -> **总结** -> -> 1. **自动提交** -> -> - 查看自动提交状态:`SELECT @@AUTOCOMMIT` ; -> -> - 设置自动提交状态:`SET AUTOCOMMIT = 0` 。 -> -> 2. **手动提交** -> -> `@@AUTOCOMMIT = 0` 时,使用 `COMMIT` 命令提交事务。 -> -> 3. **事务回滚** -> -> `@@AUTOCOMMIT = 0` 时,使用 `ROLLBACK` 命令回滚事务。 - -**事务的实际应用**,让我们再回到银行转账项目: - -```mysql --- 转账 -UPDATE user set money = money - 100 WHERE name = 'a'; - --- 到账 -UPDATE user set money = money + 100 WHERE name = 'b'; - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -+----+------+-------+ -``` - -这时假设在转账时发生了意外,就可以使用 `ROLLBACK` 回滚到最后一次提交的状态: - -```mysql --- 假设转账发生了意外,需要回滚。 -ROLLBACK; - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -| 2 | b | 1000 | -+----+------+-------+ -``` - -这时我们又回到了发生意外之前的状态,也就是说,事务给我们提供了一个可以反悔的机会。假设数据没有发生意外,这时可以手动将数据真正提交到数据表中:`COMMIT` 。 - -### 手动开启事务 - BEGIN / START TRANSACTION - -事务的默认提交被开启 ( `@@AUTOCOMMIT = 1` ) 后,此时就不能使用事务回滚了。但是我们还可以手动开启一个事务处理事件,使其可以发生回滚: - -```mysql --- 使用 BEGIN 或者 START TRANSACTION 手动开启一个事务 --- START TRANSACTION; -BEGIN; -UPDATE user set money = money - 100 WHERE name = 'a'; -UPDATE user set money = money + 100 WHERE name = 'b'; - --- 由于手动开启的事务没有开启自动提交, --- 此时发生变化的数据仍然是被保存在一张临时表中。 -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -+----+------+-------+ - --- 测试回滚 -ROLLBACK; - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 1000 | -| 2 | b | 1000 | -+----+------+-------+ -``` - -仍然使用 `COMMIT` 提交数据,提交后无法再发生本次事务的回滚。 - -```mysql -BEGIN; -UPDATE user set money = money - 100 WHERE name = 'a'; -UPDATE user set money = money + 100 WHERE name = 'b'; - -SELECT * FROM user; -+----+------+-------+ -| id | name | money | -+----+------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -+----+------+-------+ - --- 提交数据 -COMMIT; - --- 测试回滚(无效,因为表的数据已经被提交) -ROLLBACK; -``` - -### 事务的 ACID 特征与使用 - -**事务的四大特征:** - -- **A 原子性**:事务是最小的单位,不可以再分割; -- **C 一致性**:要求同一事务中的 SQL 语句,必须保证同时成功或者失败; -- **I 隔离性**:事务1 和 事务2 之间是具有隔离性的; -- **D 持久性**:事务一旦结束 ( `COMMIT` ) ,就不可以再返回了 ( `ROLLBACK` ) 。 - -### 事务的隔离性 - -**事务的隔离性可分为四种 ( 性能从低到高 )** : - -1. **READ UNCOMMITTED ( 读取未提交 )** - - 如果有多个事务,那么任意事务都可以看见其他事务的**未提交数据**。 - -2. **READ COMMITTED ( 读取已提交 )** - - 只能读取到其他事务**已经提交的数据**。 - -3. **REPEATABLE READ ( 可被重复读 )** - - 如果有多个连接都开启了事务,那么事务之间不能共享数据记录,否则只能共享已提交的记录。 - -4. **SERIALIZABLE ( 串行化 )** - - 所有的事务都会按照**固定顺序执行**,执行完一个事务后再继续执行下一个事务的**写入操作**。 - -查看当前数据库的默认隔离级别: - -```mysql --- MySQL 8.x, GLOBAL 表示系统级别,不加表示会话级别。 -SELECT @@GLOBAL.TRANSACTION_ISOLATION; -SELECT @@TRANSACTION_ISOLATION; -+--------------------------------+ -| @@GLOBAL.TRANSACTION_ISOLATION | -+--------------------------------+ -| REPEATABLE-READ | -- MySQL的默认隔离级别,可以重复读。 -+--------------------------------+ - --- MySQL 5.x -SELECT @@GLOBAL.TX_ISOLATION; -SELECT @@TX_ISOLATION; -``` - -修改隔离级别: - -```mysql --- 设置系统隔离级别,LEVEL 后面表示要设置的隔离级别 (READ UNCOMMITTED)。 -SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; - --- 查询系统隔离级别,发现已经被修改。 -SELECT @@GLOBAL.TRANSACTION_ISOLATION; -+--------------------------------+ -| @@GLOBAL.TRANSACTION_ISOLATION | -+--------------------------------+ -| READ-UNCOMMITTED | -+--------------------------------+ -``` - -#### 脏读 - -测试 **READ UNCOMMITTED ( 读取未提交 )** 的隔离性: - -```mysql -INSERT INTO user VALUES (3, '小明', 1000); -INSERT INTO user VALUES (4, '淘宝店', 1000); - -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -+----+-----------+-------+ - --- 开启一个事务操作数据 --- 假设小明在淘宝店买了一双800块钱的鞋子: -START TRANSACTION; -UPDATE user SET money = money - 800 WHERE name = '小明'; -UPDATE user SET money = money + 800 WHERE name = '淘宝店'; - --- 然后淘宝店在另一方查询结果,发现钱已到账。 -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 200 | -| 4 | 淘宝店 | 1800 | -+----+-----------+-------+ -``` - -由于小明的转账是在新开启的事务上进行操作的,而该操作的结果是可以被其他事务(另一方的淘宝店)看见的,因此淘宝店的查询结果是正确的,淘宝店确认到账。但就在这时,如果小明在它所处的事务上又执行了 `ROLLBACK` 命令,会发生什么? - -```mysql --- 小明所处的事务 -ROLLBACK; - --- 此时无论对方是谁,如果再去查询结果就会发现: -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -+----+-----------+-------+ -``` - -这就是所谓的**脏读**,一个事务读取到另外一个事务还未提交的数据。这在实际开发中是不允许出现的。 - -#### 读取已提交 - -把隔离级别设置为 **READ COMMITTED** : - -```mysql -SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT @@GLOBAL.TRANSACTION_ISOLATION; -+--------------------------------+ -| @@GLOBAL.TRANSACTION_ISOLATION | -+--------------------------------+ -| READ-COMMITTED | -+--------------------------------+ -``` - -这样,再有新的事务连接进来时,它们就只能查询到已经提交过的事务数据了。但是对于当前事务来说,它们看到的还是未提交的数据,例如: - -```mysql --- 正在操作数据事务(当前事务) -START TRANSACTION; -UPDATE user SET money = money - 800 WHERE name = '小明'; -UPDATE user SET money = money + 800 WHERE name = '淘宝店'; - --- 虽然隔离级别被设置为了 READ COMMITTED,但在当前事务中, --- 它看到的仍然是数据表中临时改变数据,而不是真正提交过的数据。 -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 200 | -| 4 | 淘宝店 | 1800 | -+----+-----------+-------+ - - --- 假设此时在远程开启了一个新事务,连接到数据库。 -$ mysql -u root -p12345612 - --- 此时远程连接查询到的数据只能是已经提交过的 -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -+----+-----------+-------+ -``` - -但是这样还有问题,那就是假设一个事务在操作数据时,其他事务干扰了这个事务的数据。例如: - -```mysql --- 小张在查询数据的时候发现: -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 200 | -| 4 | 淘宝店 | 1800 | -+----+-----------+-------+ - --- 在小张求表的 money 平均值之前,小王做了一个操作: -START TRANSACTION; -INSERT INTO user VALUES (5, 'c', 100); -COMMIT; - --- 此时表的真实数据是: -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -| 5 | c | 100 | -+----+-----------+-------+ - --- 这时小张再求平均值的时候,就会出现计算不相符合的情况: -SELECT AVG(money) FROM user; -+------------+ -| AVG(money) | -+------------+ -| 820.0000 | -+------------+ -``` - -虽然 **READ COMMITTED** 让我们只能读取到其他事务已经提交的数据,但还是会出现问题,就是**在读取同一个表的数据时,可能会发生前后不一致的情况。**这被称为**不可重复读现象 ( READ COMMITTED )** 。 - -#### 幻读 - -将隔离级别设置为 **REPEATABLE READ ( 可被重复读取 )** : - -```mysql -SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; -SELECT @@GLOBAL.TRANSACTION_ISOLATION; -+--------------------------------+ -| @@GLOBAL.TRANSACTION_ISOLATION | -+--------------------------------+ -| REPEATABLE-READ | -+--------------------------------+ -``` - -测试 **REPEATABLE READ** ,假设在两个不同的连接上分别执行 `START TRANSACTION` : - -```sql --- 小张 - 成都 -START TRANSACTION; -INSERT INTO user VALUES (6, 'd', 1000); - --- 小王 - 北京 -START TRANSACTION; - --- 小张 - 成都 -COMMIT; -``` - -当前事务开启后,没提交之前,查询不到,提交后可以被查询到。但是,在提交之前其他事务被开启了,那么在这条事务线上,就不会查询到当前有操作事务的连接。相当于开辟出一条单独的线程。 - -无论小张是否执行过 `COMMIT` ,在小王这边,都不会查询到小张的事务记录,而是只会查询到自己所处事务的记录: - -```sql -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -| 5 | c | 100 | -+----+-----------+-------+ -``` - -这是**因为小王在此之前开启了一个新的事务 ( `START TRANSACTION` ) **,那么**在他的这条新事务的线上,跟其他事务是没有联系的**,也就是说,此时如果其他事务正在操作数据,它是不知道的。 - -然而事实是,在真实的数据表中,小张已经插入了一条数据。但是小王此时并不知道,也插入了同一条数据,会发生什么呢? - -```sql -INSERT INTO user VALUES (6, 'd', 1000); --- ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY' -``` - -报错了,操作被告知已存在主键为 `6` 的字段。这种现象也被称为**幻读,一个事务提交的数据,不能被其他事务读取到**。 - -#### 串行化 - -顾名思义,就是所有事务的**写入操作**全都是串行化的。什么意思?把隔离级别修改成 **SERIALIZABLE** : - -```mysql -SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT @@GLOBAL.TRANSACTION_ISOLATION; -+--------------------------------+ -| @@GLOBAL.TRANSACTION_ISOLATION | -+--------------------------------+ -| SERIALIZABLE | -+--------------------------------+ -``` - -还是拿小张和小王来举例: - -```mysql --- 小张 - 成都 -START TRANSACTION; - --- 小王 - 北京 -START TRANSACTION; - --- 开启事务之前先查询表,准备操作数据。 -SELECT * FROM user; -+----+-----------+-------+ -| id | name | money | -+----+-----------+-------+ -| 1 | a | 900 | -| 2 | b | 1100 | -| 3 | 小明 | 1000 | -| 4 | 淘宝店 | 1000 | -| 5 | c | 100 | -| 6 | d | 1000 | -+----+-----------+-------+ - --- 发现没有 7 号王小花,于是插入一条数据: -INSERT INTO user VALUES (7, '王小花', 1000); -``` - -此时会发生什么呢?由于现在的隔离级别是 **SERIALIZABLE ( 串行化 )** ,串行化的意思就是:假设把所有的事务都放在一个串行的队列中,那么所有的事务都会按照**固定顺序执行**,执行完一个事务后再继续执行下一个事务的**写入操作** ( **这意味着队列中同时只能执行一个事务的写入操作** ) 。 - -根据这个解释,小王在插入数据时,会出现等待状态,直到小张执行 `COMMIT` 结束它所处的事务,或者出现等待超时。 diff --git "a/\347\233\270\345\205\263\344\271\246\347\261\215\351\223\276\346\216\245\344\270\213\350\275\275.md" "b/\347\233\270\345\205\263\344\271\246\347\261\215\351\223\276\346\216\245\344\270\213\350\275\275.md" deleted file mode 100644 index b64ea27..0000000 --- "a/\347\233\270\345\205\263\344\271\246\347\261\215\351\223\276\346\216\245\344\270\213\350\275\275.md" +++ /dev/null @@ -1,48 +0,0 @@ -# 1 Java类数据 - -## 1.1 深入理解Java虚拟机 -此书配上牛客网Java测试题,那家伙,美滋滋啊! - -```jshelllanguage -链接:https://pan.baidu.com/s/17HMumeM_LDrU23F7BTFT8A -提取码:1cqf -``` - -## 1.2 云原生微服务架构 - -```mysql -链接:https://pan.baidu.com/s/1K52eryXZ4HFIQ8GIBFxjMA -提取码:wmun -``` - -## 1.3 Java代码开发规范 - -```mysql -链接:https://pan.baidu.com/s/1nkXpXsyilP0kMhz016Z8Aw -提取码:n5oq -``` - -# 2 计算机“四大发明” -## 2.1 数据结构与算法 -```jshelllanguage -# 拉钩课程算法数据《300分钟搞定算法面试》 - -链接:https://pan.baidu.com/s/1YYCJ-dI73VJoucHYW3DYCQ -提取码:t0cl -``` - - - -# 3 工具 -## 3.1 IDEA工具激活:1.插件式 2.配置式 - -```mysql -链接:https://pan.baidu.com/s/1nS3DVceif_WjJ6PwAmF73g -提取码:vdt7 -``` -## 3.2 抖音60帧剪辑方法 - -```mysql -链接:https://pan.baidu.com/s/1j5lawjVd3AnwoeBCyDQjLw -提取码:d4wr -``` \ No newline at end of file diff --git "a/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\345\270\270\350\247\201\347\232\204\351\235\242\350\257\225\347\254\224\350\256\260.md" "b/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\345\270\270\350\247\201\347\232\204\351\235\242\350\257\225\347\254\224\350\256\260.md" deleted file mode 100644 index a59fb08..0000000 --- "a/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\345\270\270\350\247\201\347\232\204\351\235\242\350\257\225\347\254\224\350\256\260.md" +++ /dev/null @@ -1,144 +0,0 @@ -# Java常见的面试笔记 -- 每日一题 - -## 1.1 HashMap、ConcurrentHashMap、HashTable - -## 1.2 Java可以多继承吗? -Java不支持多继承,多继承会造成: - -1、若子类继承的父类中拥有相同的成员变量,子类在引用该变量时将无法判别使用哪个父类的成员变量 - -2、若一个子类继承的多个父类拥有相同方法,同时子类并未覆盖该方法(若覆盖,则直接使用子类中该方法),那么调用该方法时将无法确定调用哪个父类的方法。 - -Java为了简单,废弃了C++中非常容易混淆的多继承等特性。 - -```java -class fatherA{ - void fa(){ - System.out.println("fatherA:A"); - } -} -public class demo extends fatherA{ - void fa(){ - System.out.println("demo:A"); - super.fa(); - } - public static void main(String[] args){ - demo demo = new demo(); - demo.fa(); - } -} -``` -输出: - -``` -demo:A -fatherA:A -``` - - -## 2 多线程 - -### 2.1 程序运行结果 - -```java -public static void main(String args[]) { - - Thread t = new Thread() { -public void run() { -pong(); -} -}; - -t.run(); -System.out.print("ping"); - - } - - - static void pong() { - System.out.print("pong"); -} - -``` - -运行结果: pongping - -解析:t.run是调用的Thead类中的run()方法,t.start才是执行线程,所以这题就是执行普通run()方法,先输出pong,在输出ping。 - -### 2.2 值传递和引用传递 - -数据类型 - -Java的基本数据类型都有长度固定的数据位,不随运行平台的变化而变化 - -引用类型都是**类**或**对象**实现的 - -> 注意:Java不支持C/C++语言的指针类型、结构类型(struct)、联合类型(union)。在JDK5.0中提供对象对枚举类型的支持 - -#### 2.2.1 值传递(基本数据类型的传递) - -`实参`传递给形参的是`值` `形参`和`实参`在内存上是两个独立的变量 -对形参做任何修改不会影响实参 - -代码示例: - -```java -public class Demo1 { - public static void main(String[] args) { - int b =20; - change(b);// 实参 实际上的参数 - System.out.println(b); - } - public static void change(int a){//形参 形式上的参数 - a=100; - } -} -``` -结果:20 - -**为什么要用方法`static`关键字?** - -因为change(int a)创建了一个a内存空间,int -b创建了一个b内存空间,但只是把b的值赋值给a,并没有改变a的值 - -#### 2.2.2 引用传递(引用数据类型的传递) - -`实参`传递给`形参`的是参数对于堆内存上的`引用地址` - -`实参`和`形参`在内存上指向了同一块区域,对形参的修改会`影响`实参 - -```java -public class Demo2 { - public static void main(String[] args) { - int [] a={1,2,3}; - System.out.println(a[0]); - change(a); - System.out.println(a[0]); - } - public static void change(int[] a ){ - a[0]=100; - } -} -``` - -reason:由于引用传递,传递的是地址,方法改变的都是同一个地址中的值(类、数组、接口) - - -##### 2.2.3 MMU地址变换 - -##### 2.2.4 Java中private、protected、public和default的区别 - -##### 2.2.5 多态 - -##### 2.2.6 字段 abstract、final、static、this、super、null - -+ abstract - -abstract类必须被继承,abstract方法必须被重写。abstract类不能实例化,abstract方法只需声明不需实现。 -方法为abstract,其类必为abstract类(抽象类中可以没有抽象方法,但是抽象方法必须在抽象类中或者接口中) - -+ final - -final类不能被继承,且不能修改 - -## \ No newline at end of file diff --git "a/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\346\257\217\346\227\245\344\270\200\351\242\230.md" "b/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\346\257\217\346\227\245\344\270\200\351\242\230.md" deleted file mode 100644 index f6c136d..0000000 --- "a/\351\235\242\350\257\225\347\273\217\351\252\214\345\222\214\351\227\256\351\242\230\346\200\273\347\273\223/\346\257\217\346\227\245\344\270\200\351\242\230.md" +++ /dev/null @@ -1,102 +0,0 @@ -* [session和cookies的区别是什么](#session和cookies的区别是什么) - * [前言](#前言) - * [什么是Cookie](#什么是Cookie) - * [查看方法](#查看方法) - * [什么是Session](#什么是Session) - * [它们的区别--总结](#它们的区别总结) - -# 7.12 Session和Cookie的区别是什么 -## 前言 - -当用户在浏览器输入一个网址时,会从服务端返回给用户一个页面或者信息。那么**Session**就是浏览器和服务器之间的一次对话,比如浏览器问候“你好吗”,服务端回答:“你好”。 -我们用浏览器打开一个网址,用的是**http协议**,而这种协议是**无状态**的,无状态就是这次请求和上次请求时无关联的,这种无状态的好处就在于能够快速访问。 - -那么有一次场景就是当用户访问http://a.com/login.html时,用户进行登录。那当我访问http://a.com/index.html时,我们也希望它是登陆状态,但这两个页面是http协议,http协议是无状态的,是没有关联的。 -那我怎样获取登陆状态呢,一是每次登录用户时我都需要从数据库中去查找用户登录的状态并返回,但这种每次查询数据库是行不通的,会造成数据库的压力。正是这种诉求,cookie出现了,cookie是存在于浏览器端的,保存到数据库里。 -每次登录我只需在浏览器上查找是否登录过就行,但这种方式是不安全的。因为cookie存在于浏览器端,用户可以随时修改。所以session就出来了,放在服务端,相对安全。 - -## 什么是Cookie - `Cookie`意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。 -  由于**HTTP**是一种**无状态**的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。 -  Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。 - -  查看某个网站颁发的Cookie很简单。在浏览器地址栏输入`javascript:alert (document. cookie)`就可以了(需要有网才能查看)。 - -## 什么是Session - - **Session**是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而`Session保存在服务器`上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。 -  **如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份**。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了 - -## 查看方法 - -### 方法一 - 在浏览器的地址栏输入:`javascript:alert(document.cookie)` (不区分大小写),就会弹出你在当前网页登录的cookie信息。输入时javascript会自动消失,所以需要输入1javascript:alert(document.cookie),然后再删除1。 - -但这种方式我试过总是不行,不知道是哪里出现问题 - -### 方法二 - 按F12进入浏览器的开发者模式——console——在命令行输入javascript:alert(document.cookie),再回车,就可以在浏览器端查看弹出的信息了! - - - -### 方法三 - - 在Chrome中查看Cookie:点击url左边的文本图标, 单击cookie - - - -## 它们的区别总结 - -+ 1.保存位置: - session服务端,cookie客户端 - -+ 2.安全性: - session相对安全,cookie相对不安全。 - -+ 3.存储类型: - session能够存储任意的对象,cookie只能存储String类型的对象。 - -+ 4.大小限制: - session没有大小限制,cookie有大小限制(4k)。 - -+ 5.个数限制: - session没有个数限制,cookie个数限制(二十到几百个)。 - -+ 6.键值对: - session是键值对嵌套键值对,cookie是键值对。 - -+ 7.用户禁用: - session不能被用户禁用,cookie能被用户禁用。 - -+ 8.服务器压力: - session压力大,cookie压力小。 - -+ 9.生命周期:session用户浏览器关闭,cookie可长期保存。 - -+ 10.区分路径: - session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到。而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的.cookie只能是子路径访问父路径设置的cookie。 - -[推荐阅读:cookie和session的详解和区别](https://www.cnblogs.com/l199616j/p/11195667.html) - -# 7.13 什么是索引回表,如何避免(索引覆盖) - -## 什么是索引? -索引其实可以理解为书中的目录,就像你小时候用新华字典查单词一样,通过首字母依次查找想要的字幕。索引在mysql里面也叫键(key)是存储引擎用于快速快速查找记录的一种数据结构。 - -索引的一个主要目的就是加快检索表中数据,亦即能协助信息搜索者尽快的找到符合限制条件的记录ID的辅助数据结构。 - -# 7.14 es用过冷热分离吗?假如现在有些数据热变冷,有些数据冷变热,怎么解决? - -## -热变冷: -有x台机器tag设置为hot。 -有y台机器tag设置为cool。 -hot集群中只存最近两天的。 -有一个定时任务每天将前一天的索引标记为cool。 -es看到有新的标记就会将这个索引迁移到冷集群中, 这都是es自动完成的。 - -冷变热: -缓存预热。 - -# 7.15 死锁与活锁的区别,死锁与饥饿的区别? -