日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

数据库开发技术java方向_Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis...

發布時間:2023/12/19 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库开发技术java方向_Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第5章--MyBatis

MyBatis入門

Abstract: 數據庫框架的工作原理和使用方法(以MyBatis為例)

面向對象的世界與關系型數據庫的鴻溝:

面向對象世界中的數據是對象;

關系型數據庫中的數據是以行、列表示的二元表。

什么映射技術能實現對象和二元表之間的自動轉換呢?

--ORM (Object Relation Mapping)

持久化類與數據庫表之間的映射關系;對持久化對象的操作自動轉換成對關系數據庫操作。

關系數據庫的每一行映射為每一個對象;關系數據庫的每一列映射為對象的一個屬性。

MyBatis:

項目前身為Apache基金會下的開源項目iBatis

支持自定義SQL、存儲過程和高級映射的持久化框架

使用XML或注解配置

能映射基本數據元素、接口、Java對象到數據庫

本質上是ORM框架,但不同的是:

不是直接建立Java對象到關系數據庫表中數據之間的映射,而是建立對對象的操作方法到SQL語句之間的映射。

MyBatis功能架構:

API接口層:主要提供了供外部使用的API,開發人員通過這些本地API來操作數據庫;接口層接到調用請求以后,將請求轉給數據處理層去完成具體的數據處理。

數據處理層:完成數據庫的操作

基礎支撐層:最基礎的組件,為數據處理成提供支撐

MyBatis工作流機制:

在應用程序啟動時,加載一個XML文件,該文件定義了后端數據庫地址、SQL與Java之間的映射關系,根據XML或注解加載SQL語句、參數映射、結果映射到內存中;

應用程序調用API傳入參數和SQL ID

MyBatis自動生成SQL語句完成數據庫訪問,轉換執行結果返回應用程序,應用程序得到Java對象。

MyBatis環境搭建:

JAR: mybatis-3.4.5.jar:?https://github.com/mybatis/mybatis-3/releases

(由于MyBatis的底層是基于JDBC實現數據庫訪問的,所以也需要JDBC的jar包)

MyBatis配置:

SqlSessionFactory: 通過該實例可以獲取能夠將對象轉換成數據庫的這么一個session

通過xml配置文件完成SqlSessionFactory的配置

MyBatis系統的核心配置:后端數據庫連接實例的數據源、決定事務范圍和控制方式的事務管理器 (transactionManager)

將該配置文件放置于工程的根目錄下MyBatisTest/src/main/java/...xml

transactionManager的type屬性可以設置為jdbc或managed

jdbc: 表示MyBatis的事務控制其實是直接使用jdbc的提交和回滾

managed: 表示對于MyBatis的事務提交和回滾,MyBatis不會做任何事情,也不會調用jdbc的提交和回滾;事務的控制交給外部的容器,比如Spring的方式來完成

后端數據庫源:和jdbc一樣,包括driver, url, username, password.

完成了SqlSessionFactory的配置以后,就可以開始Java程序的編寫了。

MyBatis本身是ORM框架,因此需要定義一些Java對象,建立對象對對象操作和sql語句之間的映射。

在類包MyBatisTest/src/package_name/中:創建User.java和GetUserInfo.java

i.e.

構造對象:

public classUser {private intid;privateString userName;privateString corp;publicUser(Integer id, String userName, String corp) {this.id =id;this.userName =userName;this.corp =corp;

}public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getUserName() {returnuserName;

}public voidsetUserName(String userName) {this.userName =userName;

}publicString getCorp() {returncorp;

}public voidsetCorp(String corp) {this.corp =corp;

}

}

對對象的操作接口:

public interfaceGetUserInfo {public User getUser(intid);public voidaddUser(User user);public voidupdateUser(User user);public voiddeleteUser(User user);

}

完成了Java對象和對Java對象操作的接口的定義之后,

需要創建Java對象和SQL語句映射關系的配置文件

在類包MyBatisTest/src/package_name/中:創建userMaper.xml(自命名,之后注冊到SqlSessionFactory.xml中)

select id, userName, corp from MyBatisUser where id = #{id}

mapper標簽中namespace屬性:定義接口的操作類(interface name)

select標簽的id:對對象的操作(getUser())

select標簽的parameterType:傳入值的類型(parameter of getUser())

select標簽的resultType:要封裝成的類(return from getUser())

上述完成了映射關系的配置文件,

接下來需要將這些配置文件注冊到最開始的SqlSessionFactory配置文件中:

...

完成數據庫查詢的步驟:

1. 加載配置文件(應用配置文件SqlSessionFactory.xml、關聯映射文件userMapper.xml)

2. 生成SqlSessionFactory實例,獲取SqlSession

3. 利用Session執行SQL

測試類:Test.java

public classTest {public static voidmain(String[] args) {//1. 聲明配置文件的目錄地址

String resource = "SqlSessionFactory.xml";//2. 加載應用配置文件

InputStream is = Test.class.getClassLoader().getResourceAsStream(resource);//3. 創建SqlSessionFactory

SqlSessionFactory sessionFactory = newSqlSessionFactoryBuilder().build(is);//4. 獲取Session

SqlSession session =sessionFactory.openSession();try{//5. 獲取操作類

GetUserInfo getUserInfo = session.getMapper(GetUserInfo.class);//6. 查詢操作

User user = getUserInfo.getUser(2);

System.out.println(user.getId()+ ". " + user.getUserName() + ":" +user.getCorp());

}finally{//7. 關閉Session

session.close();

}

}

}

1. 因為配置文件在項目的根目錄,于是路徑直接寫文件名即可。

2. 將配置文件用InputStream加載到程序中

3. 通過上述流對象,創建SqlSessionFactory的實例

4. 從SqlSessionFactory實例中獲取session

5. 通過mapper,獲得接口

6. 通過調用接口的方法,完成具體操作

7. finally,關閉session

以上程序即可運行,但是通過兩個配置文件進行配置,會不會太繁瑣了呢?

通過注解的方式進行配置:通過注解的方式進行聲明接口與sql語句之間的映射,以替代映射文件

接口類文件GetUserInfoAnnotation.java (同上例的GetUserInfo.java)

public interfaceGetUserInfoAnnotation {

@Select("select * from user where id = #{id}")public User getUser(intid);

}

Test方法中需要配置映射關系:

Configuration conf = sessionFactory.getConfiguration();

conf.addMapper(GetUserInfoAnnotation.class);

public static voidmain(String[] args) {//1. 聲明配置文件的目錄地址

String resource = "SqlSessionFactoryAnnotation.xml";//2. 加載應用配置文件

InputStream is = TestAnnotation.class.getClassLoader().getResourceAsStream(resource);//3. 創建SqlSessionFactory

SqlSessionFactory sessionFactory = newSqlSessionFactoryBuilder().build(is);//完成配置映射關系 ******

Configuration conf =sessionFactory.getConfiguration();

conf.addMapper(GetUserInfoAnnotation.class);//4. 獲取Session

SqlSession session =sessionFactory.openSession();try{//5. 獲取操作類

GetUserInfoAnnotation getUserInfoAnnotation = session.getMapper(GetUserInfoAnnotation.class);//6. 查詢操作

User user = getUserInfoAnnotation.getUser(2);

System.out.println(user.getId()+ ". " + user.getUserName() + ":" +user.getCorp());

}finally{//7. 關閉Session

session.close();

}

}

以上代碼實現了之前mapper的作用(無需userMapper.xml文件,且在SqlSessionFactory.xml中無需添加mapper的注冊)

添加增刪改的功能:

實現接口中的addUser(User user); updateUser(User user); deleteUser(int id);功能

insert into MyBatisUser (userName, Corp) values (#{userName}, #{Corp})

update MyBatisUser SET userName=#{userName}, Corp=#{Corp} WHERE id=#{id};

delete from MyBatisUser where id=#{id};

useGeneratedKeys="true" 使用自增

keyProperty="id" 自增對應到id上

對應Test.java中:

改為SqlSessionFactory.openSession(true);

JDBC獲取數據庫連接時,默認自動進行提交,不是以事務為單位提交的;

而在MyBatis中,獲取的事務默認是開啟事務的,則默認對之后的每一個操作都是以事務的方式來提交的,需顯式調用commit()

進行數據庫操作:

public classTest {public static voidmain(String[] args) {//1. 聲明配置文件的目錄地址

String resource = "SqlSessionFactory.xml";//2. 加載應用配置文件

InputStream is = Test.class.getClassLoader().getResourceAsStream(resource);//3. 創建SqlSessionFactory

SqlSessionFactory sessionFactory = newSqlSessionFactoryBuilder().build(is);//4. 獲取Session

SqlSession session =sessionFactory.openSession();try{//5. 獲取操作類

GetUserInfo getUserInfo = session.getMapper(GetUserInfo.class);//6. 數據庫操作//add user

User user = new User("XiaoMing", "Netease");

getUserInfo.addUser(user);

System.out.println("new ID: " + user.getId()); //id : useGeneratedKey//select user

user =getUserInfo.getUser(user.getId());

System.out.println(user.getId()+ "." + user.getUserName() + ": " +user.getCorp());//update user

user.setUserName("LiMing");

getUserInfo.updateUser(user);

user=getUserInfo.getUser(user.getId());

System.out.println(user.getId()+ "." + user.getUserName() + ": " +user.getCorp());//delete user

getUserInfo.deleteUser(user.getId());

user=getUserInfo.getUser(user.getId());

System.out.println(user);

}finally{//7. 關閉Session

session.close();

}

}

}

MyBatis的優勢和劣勢

優勢:入門門檻低;可以自己編寫SQL使得更加靈活也可以進行SQL優化

劣勢:需要自己編寫SQL導致工作量大;數據庫移植性差(需要修改sql語句)

MyBatis進階

實際開發中會遇到復雜的數據庫和復雜的SQL語句

i.e.

上述ER圖中User與Course之間的關系為many-to-many, 需要一個Associative Entity

創建數據庫:studentEnrollment

./mysql -u root -p;

mysql> create databasestudentEnrollment;

mysql> grant all privileges on studentEnrollment.* to matt@localhost;

mysql> flush privileges;

mysql> exit;

./mysql -u matt -p;

mysql> usestudentEnrollment;

mysql> CREATE TABLE User(-> id int(11) NOT NULLAUTO_INCREMENT,-> userName varchar(100) NOT NULL,-> corp varchar(100) DEFAULT NULL,-> PRIMARY KEY(id)-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> CREATE TABLEteacher (-> id int(11) NOT NULLAUTO_INCREMENT,-> teacherName varchar(100) NOT NULL,-> PRIMARY KEY(id)-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> CREATE TABLEcourse (-> id int(11) NOT NULLAUTO_INCREMENT,-> CourseName varchar(100) DEFAULT NULL,-> teacher_id int(11) DEFAULT NULL,-> PRIMARY KEY(id),-> FOREIGN KEY (teacher_id) REFERENCESteacher(id)-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> CREATE TABLEUserCourse (-> id int(11) NOT NULLAUTO_INCREMENT,-> user_id int(11) DEFAULT NULL,-> course_id int(11) DEFAULT NULL,-> PRIMARY KEY(id),-> FOREIGN KEY (user_id) REFERENCES user(id),-> FOREIGN KEY (course_id) REFERENCEScourse(id)-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> INSERT INTO User VALUES (null, "XiaoMing", "Netease");

mysql> INSERT INTO Teacher VALUES (null, "Smith");

mysql> INSERT INTO Course VALUES (null, "math", 1);

mysql> INSERT INTO UserCourse VALUES (null, 1, 1);

創建對應的Java對象:User, Course, Teacher

public classUser {private intid;privateString userName;privateString corp;private Listcourses;public User(intid, String userName, String corp) {this.id =id;this.userName =userName;this.corp =corp;

}

}

// 還有其他getters和setters,省略(三個類都有)

public classCourse {private intid;privateString courseName;privateTeacher teacher;//getters and setters

}public classTeacher {private intid;privateString teacherName;//getters and setters

}

創建對象的操作的接口:UserOperation.java

三張數據庫表之間的連接查詢

public interfaceUserOperation {public User getUser(intid);

}

MyBatis中有很強大的元素ResultMap:可以實現復雜查詢結果到復雜對象關聯關系的轉化。

通過構造函數Constructor,在類實例化時注入結果:一般在關聯的時候使用

idArg:ID參數,標記結果作為ID可以幫助提高整體效能

arg:注入到構造方法的一個普通結果

在mapper配置文件userMapperConstructor.xml中

要求在User類中的構造函數的參數必須和這里的column相同。(courses沒有進行初始化)

此時若要映射getUser(),可以這么寫:

select * from user where id = #{id}

其中,resultMap="UserMap"中的"UserMap"就是上面定義的resultMap的id

不要忘記寫上SqlSessionFactory.xml哦~

到這里,已經完成了從Java類到具體字段之間的映射關系。

測試:Test.java

public classTest {public static voidmain(String[] args) {

String resource= "SqlSessionFactory.xml";

InputStream is= Test.class.getClassLoader().getResourceAsStream(resource);

SqlSessionFactory sessionFactory= newSqlSessionFactoryBuilder().build(is);

SqlSession session= sessionFactory.openSession(true);try{

UserOperation userOperation= session.getMapper(UserOperation.class);

User user= userOperation.getUser(1);

System.out.println(user.getId()+"." + user.getUserName() + ":" +user.getCorp());

}finally{

session.close();

}

}

}

但是報錯:

解決方案:將User的構造函數改為public User (Integer id, String userName, String corp) {} 即可

(原來是 public User (int id, String userName, String corp) {} )

但如何讀取User中的courses呢?-- 解決容器問題

使用resultMap中的Collection標簽:實現一對多的關聯(顧名思義:collection (a collection of complex types))

id:一個ID結果,標記結果作為ID可以幫助提高整體效能

result: 注入到字段或JavaBean屬性的普通結果

(Source: The only difference between the two is that?id?will flag the result as an identifier property to be used when comparing object instances. This helps to improve general performance, but especially performance of caching and nested result mapping (i.e. join mapping).)

在mapper.xml中的中加入標簽:(與同級)

property的值"courses"必須跟要關聯的User類中的List courses變量名一致

ofType的值為該collection的類型名

id/result中的property為course對象中的變量名id;column為database返回結果中的column

修改select語句:

select u.id as userId, userName, courseName, corp, c.id as courseId from user u left joinuserCourse ucon u.id=uc.user_id left joincourse con c.id=uc.course_idwhere u.id = #{id}

三張表User, Course, UserCourse之間的關聯,用left join合并

N.B. 由于select語句中使用了u.id as userId這個alias,所以需要將resultMap.constructor中的id column也改為"userID")

(which takes me nearly twenty minutes to fix the bug);

http://www.mybatis.org/mybatis-3/sqlmap-xml.html

Test.java中

System.out.println(user.getCourses().get(0).getCourseName()); // 得到結果"math"

Course和Teacher也有關聯,那如何實現這個呢?

Association:實現復雜類型之間的關聯

id, result:與collection中的功能相同

select語句:

select u.id as userId, userName, courseName, corp, c.id ascourseId,teacherName, t.id asteacherIdfrom user u left joinuserCourse ucon u.id=uc.user_id left joincourse con c.id=uc.course_id left jointeacher ton t.id=c.teacher_idwhere u.id = #{id}

在collection中的末尾加上association tag:(因為teacher是與course關聯的,而course在此為collection中的元素)

...

property="teacher"對應Course類中的Teacher teacher屬性名

column="teacher_id"對應數據庫中返回結果的表字段teacher_id

id/result:與collection中功能相同

Test.java中:

System.out.println(user.getCourses().get(0).getTeacher().getTeacherName());

DataSource:數據庫連接池

在MyBatis 3.0中內置了連接池,與DBCP類似

在SqlSessionFactory.xml的environment中設置DataSource type="POLLED"即為開啟連接池

有空閑連接鏈和活躍連接鏈兩個隊列,當程序需要數據庫連接時,首先會判斷如果idleConnections中有空閑連接則直接分配并執行sql;如果沒有,則會判斷activeConnections隊列中是否超過了最大活躍連接數的限制,如果沒有,就會創建新的連接加入activeConnections中;如果超過了,就會遍歷activeConnections隊列找到最早的連接判斷是否超過poolMaximunCheckoutTime,如果過期則強制使其失效并返回該連接。

連接池常用配置選項:

poolMaximunActiveConnections: 最大活躍連接數(隨著連接數增加,性能可能達到拐點,不建議設置過大))

poolMaximunIdleConnections: 最大空閑連接數(建議設置與poolMaximun相同即可)

poolMaximunCheckoutTime:在idleConnections為空且activeConnections達到最大值時檢查(詳細步驟見上)

建議設置為預期最大SQL執行時間(2~3分鐘即可)

poolTimeToWait:獲取服務器端數據庫連接的超時時間,若超過則打印日志,并重新獲取。建議使用默認值20s

連接失效:若有連接長期空閑,服務器端會把該連接關閉,而連接池不知道該連接被關閉,依然會使用該連接,則會拋出異常)

poolPingEnabled:啟用連接偵測,檢查連接池中的連接是否為有效連接(默認關閉,建議啟用)

poolPingQuery:偵測sql來探測數據庫是否存活,建議使用select 1,因為開銷小

poolPingConnectionsNotUsedFor:偵測時間,建議小于服務器端超時時間,MySQL默認8小時(則一定要小于8)

MyBatis 單元測試

本次得分為:100.00/100.00, 本次測試的提交時間為:2017-08-31

1判斷(10分)

ORM框架實現了關系數據庫中二元表與面向對象的世界中對象的映射轉換,通過ORM框架,我們可以在面向對象的編程中,通過調用對象的方法實現對關系數據庫中數據的修改。

A.√10.00/10.00

B.×

2判斷(10分)

關系數據庫中的每一列映射為每一個Java對象,每一行映射為Java對象的一個屬性。

A.√

B.×10.00/10.00

3判斷(10分)

MyBatis的前身apache 基金會下的開源項目iBatis。

A.√10.00/10.00

B.×

4判斷(10分)

MyBatis可以實現自動生成SQL語句,開發者無需自己編寫SQL語句。

A.√

B.×10.00/10.00

5判斷(10分)

SqlSessionFactory是基于MyBatis的應用中心,通過SqlSessionFactory實例可以配置后端數據庫的數據源和決定事務范圍和控制方式的的事務管理器。

A.×

B.√10.00/10.00

6判斷(10分)

通過注解的方式可以配置SQL語句和對象方法之間的映射。

A.√10.00/10.00

B.×

7判斷(10分)

association標簽可以幫助我們實現通過構造函數的方式對復雜對象注入值。

A.√

B.×10.00/10.00

8判斷(10分)

ResultMap是MyBatis最強大的元素,可以實現復雜查詢結果到復雜對象的映射。

A.√10.00/10.00

B.×

9判斷(10分)

MyBatis 3.0內置了數據庫連接池,將datasource type置為pooled,啟用數據庫連接池。

A.√10.00/10.00

B.×

10判斷(10分)

MyBatis 內置連接池維護了空閑連接和活躍連接兩個隊列,當應用需要執行SQL時,首先從活躍連接隊列中獲取連接,如果獲取不到,則創建新的連接,然后加入到活躍連接隊列中。

A.√

B.×10.00/10.00

MyBatis?作業

MyBatis課程單元作業,同學們需要認真完成MyBatis入門和進階兩門課程后,完成該作業題目。作業內容為一道編程題目。

依照學術誠信條款,我保證此回答為本人原創,所有回答中引用的外部材料已經做了出處標記。

1(100分)

有一個在線交易的電商平臺,主要包括三張數據庫業務表:

現在需要基于MyBatis數據庫ORM框架,實現讀取商品信息和用戶信息兩個功能。

商品對象和用戶對象定義如下:

每個用戶都關聯了一個Product的List,用于表示該用戶所購買的所有商品,可以通過查詢transaction表的交易記錄獲得。

操作接口定義如下:

請分別實現getProduct和getUser兩個函數方法與SQL語句的映射配置文件。

模板如下:

答:

1. 創建數據庫

CREATE TABLEProduct (

Idint AUTO_INCREMENT PRIMARY KEY,

ProductNamevarchar(100) NOT NULL,

Catalogvarchar(100) DEFAULT NULL) ENGINE=Innodb;CREATE TABLE User(

Idint AUTO_INCREMENT PRIMARY KEY,

UserNamevarchar(100) NOT NULL,

Telvarchar(11) DEFAULT NULL) ENGINE=InnoDB;CREATE TABLE Transaction(

Idint AUTO_INCREMENT PRIMARY KEY,

UserIdint NOT NULL,

ProductIdint NOT NULL,FOREIGN KEY (UserId) REFERENCES User(Id),FOREIGN KEY (ProductId) REFERENCESProduct(Id)

) ENGINE=InnoDB;INSERT INTO Product VALUES (null, "Product1", "Catalog1");INSERT INTO User VALUES (null, "User1", null);INSERT INTO Transaction VALUES (null, 1, 1);

2. 導入jdbc.jar和mybatis.jar

3. 創建src下包com.sheng.mybatis.assignment; src下的SqlSessionFactory.xml;

包中 Product.java & User.java & Op.java(如題), Test.java, 還有映射配置文件mapper.xml

4. SqlSessionFactory.xml

5. mapper.xml

select u.id as userId, userName, tel, p.id as productId

from user u left join Transaction t on t.UserId = u.id

left join Product p on p.id = t.productId

where u.id=#{id}

select * from Product where id = #{id}

6. Test.java

public classTest {public static voidmain(String[] args) {

String resource= "SqlSessionFactory.xml";

InputStream is= Test.class.getClassLoader().getResourceAsStream(resource);

SqlSessionFactory sessionFactory= newSqlSessionFactoryBuilder().build(is);

SqlSession session=sessionFactory.openSession();try{

Op op= session.getMapper(Op.class);//test getUser()

User user = op.getUser(1);

System.out.println(user.getUserName()+ " purchased: " +user.getProducts());//test getProduct()

for (intproductId: user.getProducts()) {

Product product=op.getProduct(productId);

System.out.println("productId:" + productId + " " +product.getProductName());

}

}finally{

session.close();

}

}

}

7. User.java的改動:增加一個構造函數

publicUser(Integer id, String userName, String tel) {super();this.id =id;this.userName =userName;this.tel =tel;

}

8. Output

總結

以上是生活随笔為你收集整理的数据库开发技术java方向_Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。