參考鏈接: 在Java中使用_(下劃線)作為變量名
mybatis第一天??
1.mybatis概述和環境搭建??
mybatis概述??
mybatis環境搭建??
1. 創建maven工程、添加開發依賴、創建數據庫和表;??
2. 創建domain實體類和dao??
mybatis是一門java語言編寫持久層框架,大大簡化了jdbc操作,省去了我們注冊驅動,獲取連接等細節操作。??
??
org.mybatis?
mybatis?
3.4.5?
??
mysql?
mysql-connector-java?
8.0.11?
??
junit?
junit?
4.11?
test?
??
log4j?
log4j?
1.2.12?
3. 在resource中編寫mybatis主配置文件??
4. 編寫每個dao接口的映射配置文件??
/**??
* 用戶的持久層接口??
*/??
public interface IUserDao {??
/**??
* 查詢所有操作??
* @return??
*/??
List<User> findAll();??
}??
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"??
"http://mybatis.org/dtd/mybatis-3-config.dtd">??
??
default="mysql">??
id="mysql">??
type="jdbc">??
type="pooled">??
name="driver" value="com.mysql.jdbc.Driver"/>??
name="url" value="jdbc:mysql://localhost:3306/mybatis"/>??
name="username" value="root"/>??
name="password" value="78910J"/>??
??
resource="com/itheima/dao/IUserDao.xml">??
5.注意事項??
6.測試類中測試方法編寫??
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"??
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">??
namespace="com.itheima.dao.IUserDao">//namespace:接口的路徑 定位類中方法的具體位置??
id="findAll" resultType="com.itheima.domain.User"> SELECT * FROM USER??
1.在resource中創建IUserDao.xml時,文件的位置必須和IUserDao包結構相同,創建IUserDao.xml所在目錄結??
構時要一級一級創建。??
2.映射配置文件中的mapper的namespace屬性值必須是IUserDao的全類名??
3.執行sql操作的配置id屬性必須是執行方法的名詞,例如 <select id="findAll"??
@Test??
public void testFindAll() throws IOException {??
//1.讀取SqlMapConfig.xml配置文件??
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠類??
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();??
SqlSessionFactory factory = builder.build(is);??
//3.使用SqlSessionFactory工廠創建SqlSession核心對象??
/*SqlSessionFactory是MyBatis的關鍵對象,它是個單個數據庫映射??
關系經過編譯后的內存鏡像.SqlSessionFactory對象的實例可以通??
過SqlSessionFactoryBuilder對象類獲得,而SqlSessionFactoryBuilder??
則可以從XML配置文件或一個預先定制的Configuration的實例構建出SqlSessionFactory??
的實例.每一個MyBatis的應用程序都以一個SqlSessionFactory對象的實例為核心.??
同時SqlSessionFactory也是線程安全的,SqlSessionFactory一旦被創建,應該在??
應用執行期間都存在.在應用運行期間不要重復創建多次,建議使用單例模式.SqlSessionFactory??
是創建SqlSession的工廠.*/??
SqlSession session = factory.openSession();//openSession方法默認手動提交 填寫false就是自動??
提交 當對表數據crud就需要提交事務??
//4.使用SqlSession創建接口的代理對象??
IUserDao userDao = session.getMapper(IUserDao.class);??
//5.執行查詢方法??
List<User> users = userDao.findAll();??
for (User user : users) {??
System.out.println(user);??
}??
//6.釋放資源??
is.close();??
session.close();??
}2.mybatis注解開發和編寫dao實體類方式??
mybatis注解開發??
編寫dao實現類開發??
1.在核心配置文件SqlMapConfig.xml的<mappers>中添加注解映射方式:??
<mappers>??
<mapper class="com.itheima.dao.IUserMapper"/>??
mappers>??
2.定義接口和抽象方法,在抽象方法上添加對應的注解:??
public interface IUserMapper {??
/**??
* 查詢所有用戶信息??
*/??
@Select("select * from user")??
public List<User> findList();??
}??
3.進行測試:??
@Test??
public void testFindList() throws IOException {??
//1.讀取核心配置文件??
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠類??
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();??
SqlSessionFactory factory = builder.build(is);??
//3.創建SqlSession核心對象??
SqlSession session = factory.openSession();??
//4.獲取dao代理對象??
IUserMapper mapper = session.getMapper(IUserMapper.class);??
//5.執行查詢操作??
List<User> users = mapper.findList();??
for (User user : users) {??
System.out.println(user);??
}??
//6.釋放資源??
is.close();??
session.close();??
}??
1.編寫實現類:??
public class UserDaoImpl implements IUserDao{??
//1.聲明SqlSessionFactory工廠類??
private SqlSessionFactory factory;??
//2.構造賦值??
public UserDaoImpl(SqlSessionFactory factory) {??
this.factory = factory;??
}??
@Override??
public List<User> findAll() {注意:同一個dao接口不允許配置兩種映射方式,例如:下列寫法是錯誤的??
3.自定義mybatis框架??
流程分析??
自定義mybatis流程分析.png??
alt text??
Alt text??
alt text??
新建module,根據入門案例測試方法創建缺少的接口和類??
導入資料中utils目錄中的XMLConfifigBuilder.java文件,并修改錯誤??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用查詢的相關方法,哪個namespace中的哪個id方法對應的sql??
List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");??
//3.釋放資源??
session.close();??
return users;??
}??
}??
2.進行測試??
@Test??
public void testFindAllImpl() throws IOException {??
//1.讀取核心配置文件??
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠類??
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();??
SqlSessionFactory factory = builder.build(is);??
//3.創建實現類對象并調用實現類方法查詢所有用戶信息??
UserDaoImpl dao=new UserDaoImpl(factory);??
List<User> users = dao.findAll();??
//4.遍歷輸出??
for (User user : users) {??
System.out.println(user);??
}??
//4.釋放資源??
is.close();??
}??
??
resource="com/itheima/dao/IUserDao.xml"/>??
class="com.itheima.dao.IUserDao"/>??
完成SqlSessionFactoryBuilder、SqlSessionFactory接口實現類、SqlSession接口實現類功能(實現類要自??
己創建)??
SqlSessionFactoryBuilder代碼實現??
1.添加依賴:??
<dependency>??
<groupId>dom4jgroupId>??
<artifactId>dom4jartifactId>??
<version>1.6.1version>??
dependency>??
<dependency>??
<groupId>jaxengroupId>??
<artifactId>jaxenartifactId>??
<version>1.1.6version>??
dependency>??
2.創建Configuration和Mapper兩個javabean對象??
public class Configuration {??
private String driver;??
private String url;??
private String username;??
private String password;??
private Map<String,Mapper> mappers=new HashMap<String, Mapper>();//保存多組映射信息的map集??
合??
// getter/setter方法省略??
public void setMappers(Map<String, Mapper> mappers) {??
this.mappers.putAll(mappers);??
}??
}??
public class Mapper {??
private String queryString;??
private String resultType;??
// getter/setter方法省略??
}??
/**??
* 構建者對象??
*/??
public class SqlSessionFactoryBuilder {??
/**??
* 根據配置文件輸入流對象創建工廠對象??
* @param configStream 配置文件輸入流??
* @return??
*/??
public SqlSessionFactory build(InputStream configStream) {??
//1.使用XMLConfigBuilder解析配置文件??
Configuration configuration = XMLConfigBuilder.loadConfiguration(configStream);??
System.out.println("configuration = " + configuration);??
//2.創建工廠實現類對象并返回??
return new DefaultSqlSessionFactory(configuration);DefaultSqlSessionFactory代碼實現??
DefaultSqlSession代碼實現??
}??
}??
/**??
* SqlSessionFactory接口的實現類??
*/??
public class DefaultSqlSessionFactory implements SqlSessionFactory {??
//聲明封裝主配置文件對象??
private Configuration configuration;??
public DefaultSqlSessionFactory(Configuration configuration) {??
this.configuration=configuration;??
}??
/**??
* 生產操作數據庫的核心SqlSession對象??
* @return??
*/??
public SqlSession openSession() {??
//創建SqlSession實現類對象并返回??
return new DefaultSqlSession(configuration);??
}??
}??
/**??
* 操作數據庫核心SqlSession接口的實現類??
*/??
public class DefaultSqlSession implements SqlSession {??
//聲明封裝主配置文件對象,因為getMapper需要連接和映射信息,所以需要這個配置對象??
private Configuration configuration;??
private Connection conn;??
public DefaultSqlSession(Configuration configuration) {??
this.configuration=configuration;??
//從連接池工具類中獲取連接對象??
conn= DataSourceUtils.getConnection(configuration);??
}??
/**??
* 通過動態代理的方式創建接口的實現類對象??
* @param daoClass 接口的Class對象??
* @param 返回接口實現類對象??
* @return??
*/??
public <T> T getMapper(Class<T> daoClass) {??
//創建dao代理對象并返回??
T t = (T) Proxy.newProxyInstance(daoClass.getClassLoader(),??
new Class[]{daoClass},??
new MapperProxy(configuration.getMappers(),conn));??
return t;DataSourceUtils工具類獲取連接??
InvocationHandler實現類MapperProxy的代碼實現??
}??
/**??
* 釋放資源??
*/??
public void close() {??
try {??
if (conn!=null) {??
conn.close();??
}??
} catch (SQLException e) {??
e.printStackTrace();??
}??
}??
}??
/**??
* 將來封裝連接池的工具類,目前不使用連接池??
*/??
public class DataSourceUtils {??
public static Connection getConnection(Configuration cfg) {??
//1.注冊驅動??
try {??
Class.forName(cfg.getDriver());??
//2.獲取連接??
return??
DriverManager.getConnection(cfg.getUrl(),cfg.getUsername(),cfg.getPassword());??
} catch (Exception e) {??
throw new RuntimeException(e);??
}??
}??
}??
/**??
* 當dao代理對象的方法被調用時,該監聽類的invoke方法就會執行??
*/??
public class MapperProxy implements InvocationHandler {??
//map集合的key=全類名+方法名??
private Map<String, Mapper> mappers;//封裝了sql語句和結果類型??
private Connection conn;//連接對象??
public MapperProxy(Map<String, Mapper> mappers,Connection conn) {??
this.mappers=mappers;??
this.conn=conn;??
}??
//當dao代理對象的方法被調用時,invoke方法就會執行,參數method表示代理對象調用的方法??
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {??
//1.根據執行的method方法從mappers集合中找到對應的mapper對象??
//1.1.獲取方法名將MapperProxy中需要的Executor類從資料中復制到項目的utils包下,該Executor類的selectList方法幫??
我們查詢所有信息并封裝到List中??
注意:在沒網的情況下,需要刪除SqlMapConfifig和映射文件的約束信息;??
mybatis第二天??
1.mybatis的CRUD操作??
1.1.映射配置文件IUserDao.xml信息??
String methodName = method.getName();??
//1.2.獲取全類名??
String className = method.getDeclaringClass().getName();??
//1.3.拼接map集合的key,找到對應的mapper對象??
String key=className+"."+methodName;??
System.out.println("key = " + key);??
//1.4.找到要的Mapper對象??
Mapper mapper = mappers.get(key);??
if (mapper==null) {??
//沒找到,配置的全類名有誤或者方法有誤??
throw new IllegalStateException("在"+className+"類中沒有"+methodName+"方法");??
}??
//2.調用Executor工具類的selectList方法執行查詢操作??
return new Executor().selectList(mapper,conn);??
}??
}??
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"??
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">??
namespace="com.itheima.dao.IUserDao">??
id="findAll" resultType="com.itheima.domain.User"> SELECT * from user??
id="saveUser" parameterType="com.itheima.domain.User">??
/*添加用戶信息之后查詢新用戶的id keyProperty對應的是user的id屬性*/??
keyColumn="id" keyProperty="id" resultType="int" order="AFTER">??
select last_insert_id();??
/*selectKey是后來加的,在添加用戶信息時可以先忽略*/??
insert into user values (null,#{username},#{birthday},#{sex},#{address})??
id="updateUser" parameterType="com.itheima.domain.User">1.2.封裝數據的User類省略??
1.3.測試類代碼??
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}??
where id=#{id}??
id="deleteUser" parameterType="Integer">??
delete from user where id=#{id}??
id="findById" resultType="com.itheima.domain.User" parameterType="int"> select * FROM user where id=#{id}??
id="findByName" parameterType="String" resultType="com.itheima.domain.User"> select * from user where username like #{username}??
id="findTotal" resultType="int"> select count(*) from user??
public class MybatisTest {??
private InputStream is;??
private SqlSession session;??
private IUserDao userDao;??
/**??
* 初始化mybatis??
*/??
@Before??
public void init() throws IOException {??
//1.加載核心配置文件SqlMapConfig.xml??
is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠對象??
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();??
SqlSessionFactory factory = builder.build(is);??
//3.創建核心SqlSession對象??
session = factory.openSession();??
//4.創建IUserDao對象??
userDao = session.getMapper(IUserDao.class);??
}??
/**??
* 測試查詢所有用戶信息的findAll()方法??
*/??
@Test??
public void testFindAll(){??
List<User> users = userDao.findAll();??
//遍歷打印??
for (User user : users) {System.out.println(user);??
}??
}??
/**??
* 測試保存用戶信息的saveUser()方法??
*/??
@Test??
public void testSaveUser(){??
//創建用戶信息??
User user=new User();??
user.setUsername("老周");??
user.setBirthday(new Date());??
user.setAddress("武漢");??
user.setSex("男");??
System.out.println("添加前user = " + user);??
//添加到數據??
int row = userDao.saveUser(user);??
System.out.println("影響的行數row = " + row);??
//在IUserDao.xml配置了selectKey后,添加完user就會查詢到新用戶的id并封裝到user的id屬性上。??
System.out.println("添加后user = " + user);??
}??
/**??
* 測試更新用戶信息的updateUser()方法??
*/??
@Test??
public void testUpdateUser(){??
//準備要修改用戶的信息信息??
User user=new User();??
user.setId(52);??
user.setUsername("老李");??
user.setBirthday(new Date());??
user.setAddress("孝感");??
user.setSex("女");??
//修改用戶??
int row = userDao.updateUser(user);??
System.out.println("row = " + row);??
}??
/**??
* 測試更加用戶id刪除用戶信息的deleteUser()方法??
*/??
@Test??
public void testDeleteUser(){??
//根據id刪除用戶信息??
int row = userDao.deleteUser(52);??
System.out.println("row = " + row);??
}??
/**??
* 測試根據id查詢用戶信息的findById()方法??
*/??
@Test??
public void testFindById(){??
User user = userDao.findById(50);??
System.out.println(user);2.mybatis映射配置參數和返回值類型深入學習??
2.1.parameterType傳遞pojo包裝對象??
QueryVo實體類??
映射文件配置??
}??
/**??
* 測試根據用戶名稱模糊查詢的findByName()方法??
*/??
@Test??
public void testFindByName(){??
List<User> users = userDao.findByName("%王%");??
for (User user : users) {??
System.out.println(user);??
}??
}??
/**??
* 測試查詢總記錄條數的findTotal()方法??
*/??
@Test??
public void testFindTotal(){??
int total = userDao.findTotal();??
System.out.println("total = " + total);??
}??
/**??
* 釋放資源??
*/??
@After??
public void destory() throws IOException {??
//提交事務??
session.commit();??
//6.釋放資源??
session.close();??
is.close();??
}??
}??
public class QueryVo {??
private User user;??
public User getUser() {??
return user;??
}??
public void setUser(User user) {??
this.user = user;??
}??
}測試類測試方法編寫??
mybatis的dao層開發模式??
返回值類型-javabean的屬性和表字段名一致情況(了解)??
javabean實體類??
id="findByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User"> /*username是user的屬性,user是QueryVo的屬性*/ select * from user where username like #{user.username}??
/**??
* 測試根據 QueryVo 中的條件查詢用戶的findByVo()方法??
*/??
@Test??
public void testFindByVo(){??
//創建QueryVo對象??
QueryVo queryVo=new QueryVo();??
//創建模糊查詢條件封裝到user對象中??
User user=new User();??
user.setUsername("%王%");??
queryVo.setUser(user);??
//執行查詢??
List<User> users = userDao.findByVo(queryVo);??
//遍歷打印??
for (User u : users) {??
System.out.println(u);??
}??
}??
* 基于DAO代理方式(推薦使用)??
* CRUD操作(保存操作|修改操作|刪除操作|查詢一個|模糊查詢|單值查詢|獲取保存對象的id)??
* 模糊查詢需要注意??
* 獲取保存對象的id??
* 輸入參數 parameterType屬性??
* 輸入參數的類型:int、string、User、plain old java object、包裝類型ValueObject??
* 輸出參數 resultType屬性、??
* 輸入參數的類型:User、int、string??
* 解決實體類屬性和數據庫列名不對應??
* 在sql語句上取別名, 對應, 簡單??
* 通過resultMap屬性來映射java對象和數據庫列名之間的關系??
* <result property="userName" column="username">result>??
property 遵循的是駝峰規則; column 單詞下劃線隔開解決辦法1:sql的結果集使用別名,別名和javabean的屬性一致??
好處:查詢效率高;弊端:書寫麻煩,開發效率低。??
解決辦法2:使用mybatis給我們提供的配置結果集映射??
好處:id="UMap"的可以重復使用,開發效率高;弊端:查詢效率略低。??
編寫測試類測試方法??
public class U {??
private Integer userId;??
private String userName;??
private Date userBirthday;??
private String userSex;??
private String userAddress;??
//自動生成setter、getter、toString省略,此時屬性和表的字段名不一致??
}??
id="findAllU" resultType="com.itheima.domain.U"> select id userId,username userName,birthday userBirthday,sex userSex,address userAddress from user;??
id="UMap" type="com.itheima.domain.U">??
column="id" property="userId"/>??
column="username" property="userName"/>??
column="birthday" property="userBirthday"/>??
column="sex" property="userSex"/>??
column="address" property="userAddress"/>??
id="findAllU" resultMap="UMap"> select * from user; 3.mybatis中編寫dao實現類的使用(了解)??
UserDaoImpl實現類代碼??
/**??
* 測試使用別名,查詢所有用戶信息的findAllU()方法??
*/??
@Test??
public void testFindAllU(){??
List<U> us = userDao.findAllU();??
//遍歷打印??
for (U u : us) {??
System.out.println(u);??
}??
}??
public class UserDaoImpl implements IUserDao {??
private SqlSessionFactory factory;??
//接收工廠對象,用于創建SqlSession對象??
public UserDaoImpl(SqlSessionFactory factory) {??
this.factory = factory;??
}??
@Override??
public List<User> findAll() {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用selectList方法查詢所有用戶信息??
List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll");??
//3.釋放資源??
session.close();??
return users;??
}??
@Override??
public int saveUser(User user) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用insert方法添加一條用戶信息??
int row = session.insert("com.itheima.dao.IUserDao.saveUser", user);??
//3.提交并釋放資源??
session.commit();??
session.close();??
//返回影響的函數??
return row;??
}??
@Override??
public int updateUser(User user) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用update方法修改一條用戶信息??
int row = session.update("com.itheima.dao.IUserDao.updateUser", user);??
//3.提交并釋放資源session.commit();??
session.close();??
//返回影響的函數??
return row;??
}??
@Override??
public int deleteUser(int id) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用delete方法刪除一條用戶信息??
int row = session.delete("com.itheima.dao.IUserDao.deleteUser", id);??
//3.提交并釋放資源??
session.commit();??
session.close();??
//返回影響的函數??
return row;??
}??
@Override??
public User findById(Integer id) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用selectList方法查詢所有用戶信息??
User user = session.selectOne("com.itheima.dao.IUserDao.findById",id);??
//3.釋放資源??
session.close();??
return user;??
}??
@Override??
public List<User> findByName(String username) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用selectList方法根據username模糊查詢所有用戶信息??
List<User> users = session.selectList("com.itheima.dao.IUserDao.findByName",username);??
//3.釋放資源??
session.close();??
return users;??
}??
@Override??
public int findTotal() {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用delete方法刪除一條用戶信息??
int total = session.selectOne("com.itheima.dao.IUserDao.findTotal");??
//3.釋放資源??
session.close();??
//返回總記錄數??
return total;??
}??
@Override??
public List<User> findByVo(QueryVo vo) {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用selectList方法根據vo.user.username模糊查詢所有用戶信息修改測試類init方法和destory方法即可,其他測試方法都不需要改??
4.mybatis中編寫dao實現類的使用過程分析??
5.properties標簽、typeAliases標簽、package標簽使用??
5.1.properties標簽的作用??
List<User> users =??
session.selectList("com.itheima.dao.IUserDao.findByName",vo.getUser().getUsername());??
//3.釋放資源??
session.close();??
return users;??
}??
@Override??
public List<U> findAllU() {??
//1.創建核心的SqlSession對象??
SqlSession session = factory.openSession();??
//2.調用selectList方法查詢所有用戶信息??
List<U> us = session.selectList("com.itheima.dao.IUserDao.findAllU");??
//3.釋放資源??
session.close();??
return us;??
}??
}??
@Before??
public void init() throws IOException {??
//1.加載核心配置文件SqlMapConfig.xml??
is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠對象??
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();??
SqlSessionFactory factory = builder.build(is);??
/*如果是使用dao代理方式,則需要創建SqlSession對象,并獲取dao的代理對象*/??
/*//3.創建核心SqlSession對象??
session = factory.openSession();??
//4.創建IUserDao對象??
userDao = session.getMapper(IUserDao.class);*/??
/*如果使用的是自定義dao實現類方法,則需要創建dao實現類對象,并傳遞factory工廠對象*/??
userDao=new UserDaoImpl(factory);??
}??
@After??
public void destory() throws IOException {??
//提交事務,如果是自定義dao實現類就不需要,在實現類內部提交??
//session.commit();??
//6.釋放資源,如果是自定義dao實現類就不需要,在實現類內部關閉??
//session.close();??
is.close();??
}作用:將連接數據庫的信息單獨配置到一個properties屬性文件中,配置方式如下??
外部jdbcConfifig.properties配置文件??
在SqlMapConfifig.xml跟標簽下使用properties標簽引入jdbcConfifig.properties??
在dataSource中引入外部properties的各個屬性??
5.2.typeAliases標簽、package標簽使用作用??
SqlMapConfifig.xml跟標簽下使用typeAliases標簽作用 :javabean取別名(了解)??
jdbc.driver=com.mysql.jdbc.Driver??
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai??
jdbc.username=root??
jdbc.password=78910J??
??
name="driver" value="com.mysql.jdbc.Driver"/>??
name="url" value="jdbc:mysql://localhost:3306/mybatis???
serverTimezone=Asia/Shanghai"/>??
name="username" value="root"/>??
name="password" value="78910J"/>??
或者??
resource="jdbcConfig.properties">??
或者??
url="??
file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.prop??
erties">??
type="pooled">??
name="driver" value="${jdbc.driver}"/>??
name="url" value="${jdbc.url}"/>??
name="username" value="${jdbc.username}"/>??
name="password" value="${jdbc.password}"/>??
typeAliases標簽下使用package標簽作用 :指定包下的所有javabean的類名就是其別名,不區分大小寫??
(實用)??
Mappers標簽下使用package標簽作用 :不用寫mapper標簽,resources或class指定包下所有dao對應的??
映射文件都不用引入了,并且可以找到dao的接口或者dao接口對應的配置。(實用)??
mybatis第三天??
1.mybatis中連接池以及事務管理??
1.1 mybatis連接池??
mybatis中三種數據源介紹??
在sqlMapConfifig.xml中配置??
??
type="com.itheima.domain.User" alias="user"/>??
??
??
name="com.itheima.dao"/>??
UNPOOLED 不使用連接池的數據源,需要連接對象就使用DriverManager創建獲取一個,使用完成就直接銷毀??
POOLED 使用連接池的數據源 (很常用)??
JNDI 使用 JNDI 實現的數據源(最后講解,了解)1.2 mybatis事務管理??
mybatis中默認是開啟也是,也就是增刪改之后需要手動session.commit()方法手動提交事務;但是我們也可以設??
置自動提交,在增刪改完成之后不需要手動調用session.commit()提交事務。只需要在session =??
factory.openSession(true);參數true表示自動提交。??
2.mybatis中動態SQL??
使用場景:如果條件存在就帶條件查詢,如果條件不存在就不帶條件查詢,適用于搜索等場景。??
2.1 if標簽 - 動態添加條件??
在IUserDao.xml中配置查詢語句??
2.2 where 標簽 - 代替where 1=1??
在IUserDao.xml中修改之前配置的查詢語句??
在sqlMapConfig.xml中配置如下??
type="pooled">??
name="driver" value="${jdbc.driver}"/>??
name="url" value="${jdbc.url}"/>??
name="username" value="${jdbc.username}"/>??
name="password" value="${jdbc.password}"/>??
MyBatis 在初始化時,根據的 type 屬性來創建相應類型的的數據源 DataSource,即:??
type="POOLED": MyBatis 會創建 PooledDataSource 實例??
type="UNPOOLED": MyBatis 會創建 UnpooledDataSource 實例??
type="JNDI": MyBatis 會從 JNDI 服務上查找 DataSource 實例,然后返回使用??
id="findUserByCondition1" parameterType="user" resultType="user"> select * from user where 1=1 test="username!=null and username!=''">//連接判斷條件不能為&&和|| and username = #{username} test="sex!=null"> and sex = #{sex} 2.3 foreach標簽 - 遍歷,適用于in的條件??
foreach元素的屬性主要有 item,index,collection,open,separator,close。??
item: 循環體中的具體對象。支持屬性的點路徑訪問,如 item.age,item.info.details。具體說明:在 list 和數??
組中是其中的對象,在 map 中是 value,該參數為必選。(它是每一個元素進行迭代時的別名)??
index:在 list 和數組中,index 是元素的序號;在 map 中,index 是元素的 key。??
open :表示該語句以什么開始??
separator :表示在每次進行迭代之間以什么符號作為分隔符??
close :表示以什么結束??
_parameter :不只是方法傳遞過來的參數可以被用來判斷,取值??
_parameter:代表整個參數??
單個參數:_parameter就是這個參數??
多個參數: 1.參數會被封裝為一個map:_parameter就是代表這個map??
2._parameter 可以get(0)得到第一個參數。??
在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該??
屬性的值是不一樣的,主要有一下3種情況:??
1.如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list??
2.如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array??
3.如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map??
遍歷map集合??
id="findUserByCondition1" parameterType="user" resultType="user"> select * from user test="username!=null and username!=''"> and username = #{username} test="sex!=null"> and sex = #{sex} 需求:根據qv中list集合查詢用戶信息-??
在IUserDao.xml中配置查詢語句??
測試類中測試- QueryVo中添加ids屬性省略了??
id="findByMap" parameterType="map" resultType="cn.itcast.mybatis.pojo.Product"> select * from user collection="_parameter" index="key" item="value" separator="and"> test="value !=null"> ${key} = #{value}??
id="findUserByCondition2" parameterType="QueryVo" resultType="user"> select * from user test="ids!=null and ids.size>0"> id="findUserByCondition2" parameterType="QueryVo" resultType="user">??
select * from user??
??
test="ids!=null and ids.size>0">??
and id in(??
collection="ids" item="uid" separator=",">??
#{uid}??
)??
@Test??
public void testFindUserByCondition2(){??
QueryVo qv=new QueryVo();??
List<Integer> ids=new ArrayList<Integer>();??
ids.add(41);2.4 補充1:抽取公共的sql語句??
在IUserDao.xml中跟標簽中使用sql標簽定義公共sql語句??
在中使用標簽引入公共sql 3.mybatis多表之間關系 3.1 一對一關系 需求:一個賬戶只屬于一個用戶,查詢賬戶信息的同時查詢用戶信息 實現步驟: 一對一映射 代碼示例: 1.創建Account實體類以及IAccountDao接口 ids.add(45); ids.add(46); ids.add(48); qv.setIds(ids); List<User> list = userDao.findUserByCondition2(qv); //變量展示 for (User u : list) { System.out.println("u = " + u); } } id="selectTemplate"> select * from user id="findAll" resultType="com.itheima.domain.User">??
refid="selectTemplate"/>??
1.創建Account實體類以及IAccountDao接口??
2.創建IAccountDao.xml映射問題??
3.創建AccountDaoTest測試類進行測試??
public class Account implements Serializable {??
private Integer id;??
private Integer uid;??
private Double money;??
//封裝對應的user對象2.創建IAccountDao.xml映射文件??
3.創建AccountTest測試類進行測試??
private User user;??
//setter、getter、toString方法省略??
}??
public interface IAccountDao {??
/**??
* 查詢所有賬號信息同時查詢對應用戶信息??
* @return??
*/??
List<Account> findAll();??
}??
namespace="com.itheima.dao.IAccountDao">??
id="accountUserMap" type="account">??
column="aid" property="id"/>??
column="uid" property="uid"/>??
column="money" property="money"/>??
property="user" javaType="user" column="uid">??
column="id" property="id"/>??
column="username" property="username"/>??
column="birthday" property="birthday"/>??
column="sex" property="sex"/>??
column="address" property="address"/>??
id="findAll" resultMap="accountUserMap"> /*注意:當多表查詢結果有相同字段名時,我們需要取別名區分*/ SELECT u.*,a.id aid,a.UID,a.MONEY FROM user u,account a where u.id=a.UID;??
@Test??
public void testFindAll(){??
//1.調用findAll方法??
List<Account> list = accountDao.findAll();??
//2.遍歷打印結果??
for (Account account : list) {??
System.out.println(account);??
}??
}注意:當多表查詢結果有相同字段名時,我們需要取別名區分??
3.2 一對多關系??
需求:一個用戶有多個賬戶,查詢用戶信息的同時查詢其所有賬戶信息??
實現步驟??
一對多映射??
代碼示例??
在IUserDao中添加新的查詢方法??
在IUserDao.xml中重新配置查詢語句??
編寫UserTest測試類進行測試??
1.在user中添加List<Account> accounts屬性,在IUserDao中添加新的查詢方法??
2.在IUserDao.xml中重新配置查詢語句??
3.在AccountDaoTest測試類進行測試??
/**??
* 多表查詢:查詢用戶信息的同時查詢其所有賬戶信息??
* @return??
*/??
List<User> findAllUserAndAccount();??
id="userAccountMap" type="user">??
column="id" property="id"/>??
column="username" property="username"/>??
column="birthday" property="birthday"/>??
column="sex" property="sex"/>??
column="address" property="address"/>??
property="accounts" javaType="java.util.List" ofType="account">??
column="id" property="id"/>??
column="uid" property="uid"/>??
column="money" property="money"/>??
id="findAllUserAndAccount" resultMap="userAccountMap"> SELECT * FROM user u LEFT OUTER JOIN account a ON u.id = a.UID; 3.3 多對多關系??
3.3.1 需求1:查詢角色信息以及該角色對應的所有用戶信息??
實現步驟??
代碼示例??
1.創建實體類Role以及IRoleDao接口??
/**??
* 多表查詢:查詢用戶信息的同時查詢其所有賬戶信息??
*/??
@Test??
public void testFindAllUserAndAccount(){??
List<User> users = userDao.findAllUserAndAccount();??
for (User user : users) {??
System.out.println(user);??
}??
}??
1.創建實體類Role以及IRoleDao接口??
2.創建IRoleDao.xml映射文件,并配置查詢信息??
3.創建RoleDaoTest測試類,并測試查詢方法??
public class Role {??
private Integer id;??
private String roleName;??
private String roleDesc;??
//封裝該角色對應的所有用戶信息??
private List<User> users;??
//setter、getter、toString方法省略??
}??
public interface IRoleDao {2.創建IRoleDao.xml映射文件,并配置查詢信息??
3.創建RoleDaoTest測試類,并測試查詢方法??
3.3.2 需求2:查詢用戶信息以及該用戶對應的所有角色信息??
實現步驟??
代碼示例??
/**??
* 需求1:查詢角色信息以及該角色對應的所有用戶信息??
*/??
List<Role> findAll();??
}??
namespace="com.itheima.dao.IRoleDao">??
id="roleMap" type="role">??
column="rid" property="id"/>??
column="ROLE_NAME" property="roleName"/>??
column="ROLE_DESC" property="roleDesc"/>??
property="users" javaType="java.util.List" ofType="user">??
column="id" property="id"/>??
column="username" property="username"/>??
column="birthday" property="birthday"/>??
column="sex" property="sex"/>??
column="address" property="address"/>??
id="findAll" resultMap="roleMap"> SELECT r.ID rid,r.ROLE_NAME,r.ROLE_DESC,u.* FROM role r LEFT JOIN user_role ur ON r.ID = ur.RID LEFT JOIN user u ON ur.UID = u.id??
@Test??
public void testFindAll(){??
List<Role> roles = roleDao.findAll();??
for (Role role : roles) {??
System.out.println(role);??
}??
}??
1.在實體類User中添加List<Role> roles屬性,并在IUserDao中添加新的查詢方法??
2.在IUserDao.xml中重新配置查詢語句??
3.在UserDaoTest測試類進行測試1.在IUserDao中添加新的查詢方法??
2.在IUserDao.xml中重新配置查詢語句??
3.在UserDaoTest測試類進行測試??
4.補充:JNDI??
mybatis第四天??
1.mybatis延遲加載??
1.1 概念??
/**??
* 需求2:查詢用戶信息以及該用戶對應的所有角色信息??
*/??
List<User> findAllUserAndRole();??
id="userRoleMap" type="user">??
column="id" property="id"/>??
column="username" property="username"/>??
column="birthday" property="birthday"/>??
column="sex" property="sex"/>??
column="address" property="address"/>??
property="roles" javaType="java.util.List" ofType="role">??
column="rid" property="id"/>??
column="ROLE_NAME" property="roleName"/>??
column="ROLE_DESC" property="roleDesc"/>??
id="findAllUserAndRole" resultMap="userRoleMap"> SELECT u.*,r.ID rid,r.ROLE_NAME,r.ROLE_DESC FROM user u LEFT JOIN user_role ur ON u.id = ur.UID LEFT JOIN role r ON ur.RID = r.ID;??
@Test??
public void testFindAllUserAndRole(){??
List<User> users = userDao.findAllUserAndRole();??
for (User user : users) {??
System.out.println(user);??
}??
}1.2 一對一實現延遲加載??
1.2.1 在主配置文件SqlMapConfifig.xml中開啟全局延遲加載??
1.2.2 在映射配置文件IAccountDao.xml中配置延遲加載查詢??
1.2.3 在AccountDaoTest測試類中進行測試??
1.3 一對多實現延遲加載??
1.3.1 在映射配置文件IUserDao.xml中配置延遲加載查詢??
1.立即加載:只要一調用方法,不管用不用的到數據都立馬去關聯查詢??
2.延遲加載:只有再用到數據時才去關聯查詢,不用就不關聯查詢,好處:先從單表查詢,需要時再從關聯表去關聯查??
詢,大大提高數據庫性能;延遲加載也叫按需加載或懶加載??
??
name="lazyLoadingEnabled" value="true"/>??
name="aggressiveLazyLoading" value="false"/>??
id="accountMap" type="account">??
column="id" property="id"/>??
column="uid" property="uid"/>??
column="money" property="money"/>??
property="user" javaType="user" column="uid"??
select="com.itheima.dao.IUserDao.findById"/>??
id="findAll" resultMap="accountMap"> select * FROM account??
/**??
* 延遲加載:查詢所有賬號信息同時查詢對應用戶信息??
*/??
@Test??
public void testFindAll() {??
List<Account> accounts = accountDao.findAll();??
/*只要不調用和user相關的方法,就不會查關聯表中的數據*/??
for (Account account : accounts) {??
System.out.println(account.getId()+","+account.getUid()+","+account.getMoney());??
}??
}1.3.2 在IAccountDao中添加fifindAccountById方法并在IAccountDao.xml配置??
1.3.3 在UserDaoTest測試類中進行測試??
2.mybatis中的一級緩存和二級緩存??
2.1 緩存的概念??
2.2 一級緩存??
概念??
id="userMap" type="user">??
column="id" property="id"/>??
column="username" property="username"/>??
column="birthday" property="birthday"/>??
column="sex" property="sex"/>??
column="address" property="address"/>??
property="accounts" ofType="account"??
select="com.itheima.dao.IAccountDao.findAccountById" column="id"/>??
id="findAll" resultMap="userMap"> SELECT * FROM USER ;??
id="findAccountById" parameterType="int" resultType="account"> SELECT * FROM account where uid=#{uid};??
@Test??
public void testFindAll() {??
List<User> list = userDao.findAll();??
for (User u : list) {??
System.out.println(u.getId()+","+u.getUsername()+","+u.getBirthday()+","+u.getSex()+","+u.getAd??
dress());??
/*只要不調用和account相關的方法,就不會查關聯表中的數據*/??
/*System.out.println(u.getAccounts());*/??
}??
}??
存在內存中的臨時數據就是緩存代碼演示??
結果說明??
2.3 二級緩存??
概念??
代碼演示??
它指的是Mybatis中SqlSession對象的緩存。當我們執行查詢之后,查詢的結果會同時存入到SqlSession為我們??
提供一塊區域中。該區域的結構是一個Map。當我們再次查詢同樣的數據,mybatis會先去sqlsession中查詢是否有,有??
的話直接拿出來用。當SqlSession對象消失時(close方法被調用),mybatis的一級緩存也就消失了。??
@Test??
public void testFirstLeverCache(){??
User user1 = userDao.findById(43);??
System.out.println("user1 = " + user1);??
//測試一下關閉session??
/*session.close();??
session=factory.openSession(true);??
userDao=session.getMapper(IUserDao.class);*/??
//也可以清除緩存??
//session.clearCache();??
//再次執行相同的查詢??
User user2 = userDao.findById(43);??
System.out.println("user2 = " + user2);??
//判斷user1和user2是不是同一個對象??
System.out.println("user1==user2 : " + (user1==user2));??
}??
如果是同一個session對象,那么第二次查詢的user對象和第一次查詢的user對象是同一個user對象,最后打印的??
結果是true,通過控制臺日志可以看出只執行了一次查詢;當中間關閉了session或者調用clearCache方法清除緩存之??
后,那兩個user對象就不是同一個對象了,控制臺查看日志也會發現執行了兩次查詢。??
它指的是Mybatis中SqlSessionFactory對象的緩存。由同一個SqlSessionFactory對象創建的SqlSession共享??
其緩存。??
二級緩存的使用步驟:??
第一步:讓Mybatis框架支持二級緩存(在SqlMapConfig.xml中配置)??
第二步:讓當前的映射文件支持二級緩存(在IUserDao.xml中配置)??
第三步:讓當前的操作支持二級緩存(在select標簽中配置)??
@Test??
public void testSecondLeverCache(){??
//1.獲取第一個sqlSession對象并查詢user??
SqlSession session1 = factory.openSession(true);??
IUserDao userDao1 = session1.getMapper(IUserDao.class);??
User user1 = userDao1.findById(43);結果說明以及注意事項??
3.mybatis注解開發??
3.1 mybatis注解開發CRUD操作??
3.1.1 SqlMapConfifig核心配置文件環境搭建??
System.out.println("user1 = " + user1);??
//關閉session1??
session1.close();??
//2.獲取第二個sqlSession對象并查詢user??
SqlSession session2 = factory.openSession(true);??
IUserDao userDao2 = session2.getMapper(IUserDao.class);??
User user2 = userDao2.findById(43);??
System.out.println("user2 = " + user2);??
session2.close();??
//判斷user1和user2是不是同一個對象??
System.out.println("user1==user2 : " + (user1==user2));??
}??
兩個對象雖然不是同一個對象,但是通過控制臺發現只執行了一次查詢??
注意:一定要關閉之前的sqlSession對象??
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"??
"http://mybatis.org/dtd/mybatis-3-config.dtd">??
??
resource="jdbcConfig.properties"/>??
??
name="com.itheima.domain"/>??
default="mysql">??
id="mysql">??
type="jdbc">??
type="pooled">??
name="driver" value="${jdbc.driver}"/>??
name="url" value="${jdbc.url}"/>??
name="username" value="${jdbc.username}"/>??
name="password" value="${jdbc.password}"/>??
??
name="com.itheima.dao"/>??
3.1.2 IUserDao中給方法添加注解??
/**??
* 查詢所有操作??
* @return??
*/??
@Select("select * from user")??
List<User> findAll();??
/**??
* 保存用戶??
* @param user??
* @return 影響數據庫記錄的行數??
*/??
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")??
//配置SelectKey將新添加用戶的id封裝到user中??
@SelectKey(keyColumn = "id",keyProperty = "id",resultType =int.class,before = false, statement =??
"select last_insert_id()")??
int saveUser(User user);??
/**??
* 更新用戶??
* @param user??
* @return 影響數據庫記錄的行數??
*/??
@Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}??
where id=#{id}")??
int updateUser(User user);??
/**??
* 根據 id 刪除用戶??
* @param id??
* @return 影響數據庫記錄的行數??
*/??
@Delete("delete from user where id=#{id}")??
int deleteUser(int id);??
/**??
* 根據 id 查詢??
* @param id??
* @return??
*/??
@Select("select * from user where id=#{id}")??
User findById(Integer id);??
/**??
* 根據名稱模糊查詢??
* @param username??
* @return??
*/??
@Select("select * from user where username LIKE #{username};")??
List<User> findByName(String username);??
/**3.1.3 在測試類中測試??
* 查詢總記錄條數??
* @return 總記錄條數??
*/??
@Select("select count(*) from user;")??
int findTotal();??
/**??
* 根據 QueryVo 中的條件查詢用戶??
* @param vo??
* @return??
*/??
@Select(" select * from user where username like #{user.username}")??
List<User> findByVo(QueryVo vo);??
private InputStream is;??
private SqlSession session;??
private IUserDao userDao;??
private SqlSessionFactory factory;??
@Before??
public void init() throws IOException {??
//1.獲取主配置文件輸入流??
is = Resources.getResourceAsStream("SqlMapConfig.xml");??
//2.創建SqlSessionFactory工廠對象??
factory = new SqlSessionFactoryBuilder().build(is);??
//3.創建核心SqlSession對象??
session = factory.openSession(true);??
//4.獲取IAccountDao代理對象??
userDao = session.getMapper(IUserDao.class);??
}??
//查詢所有操作??
@Test??
public void findAll(){??
List<User> users = userDao.findAll();??
for (User user : users) {??
System.out.println(user);??
}??
}??
//保存用戶??
@Test??
public void saveUser(){??
//創建用戶信息??
User user=new User();??
user.setUsername("老周");??
user.setBirthday(new Date());??
user.setAddress("武漢");??
user.setSex("男");??
System.out.println("添加前user = " + user);??
//添加到數據??
int row = userDao.saveUser(user);??
System.out.println("影響的行數row = " + row);System.out.println("添加后user = " + user);??
}??
//更新用戶??
@Test??
public void updateUser(){??
//準備要修改用戶的信息信息??
User user=new User();??
user.setId(55);??
user.setUsername("老李");??
user.setBirthday(new Date());??
user.setAddress("孝感");??
user.setSex("女");??
//修改用戶??
int row = userDao.updateUser(user);??
System.out.println("row = " + row);??
}??
//根據 id 刪除用戶??
@Test??
public void deleteUser(){??
//根據id刪除用戶信息??
int row = userDao.deleteUser(55);??
System.out.println("row = " + row);??
}??
//根據 id 查詢??
@Test??
public void findById(){??
User user = userDao.findById(50);??
System.out.println(user);??
}??
//根據名稱模糊查詢??
@Test??
public void findByName(){??
List<User> users = userDao.findByName("%王%");??
for (User user : users) {??
System.out.println(user);??
}??
}??
//查詢總記錄條數??
@Test??
public void findTotal(){??
int total = userDao.findTotal();??
System.out.println("total = " + total);??
}??
//根據 QueryVo 中的條件查詢用戶??
@Test??
public void findByVo(){??
//創建QueryVo對象??
QueryVo queryVo=new QueryVo();??
//創建模糊查詢條件封裝到user對象中??
User user=new User();??
user.setUsername("%王%");??
queryVo.setUser(user);??
//執行查詢3.2 mybatis注解開發實例類屬性與表列名不一致??
3.2.1 IUserDao中給方法添加注解??
3.2.2 在測試類中測試??
3.3 mybatis注解開發一對一/多查詢??
3.3.1 IUserDao中給方法添加注解??
List<User> users = userDao.findByVo(queryVo);??
//遍歷打印??
for (User u : users) {??
System.out.println(u);??
}??
}??
@After??
public void destroy() throws IOException {??
session.close();??
is.close();??
}??
/**??
* 使用別名,查詢所有用戶信息;??
* @return 所有用戶信息??
*/??
@Select("select * from user")??
//id="uMap"表示結果集映射的id,將來可以給其他@ResultMap復用??
@Results(id="uMap",value = {??
//id=true表示是主鍵,默認值是false??
@Result(id=true,column = "id",property = "userId"),??
@Result(id=false,column = "username",property = "userName"),??
@Result(column = "birthday",property = "userBirthday"),??
@Result(column = "sex",property = "userSex"),??
@Result(column = "address",property = "userAddress")??
}??
)??
List<U> findAllU();??
@Test??
public void findAllU(){??
List<U> us = userDao.findAllU();??
//遍歷打印??
for (U u : us) {??
System.out.println(u);??
}??
}??
/**3.3.2 IAccountDao中創建fifindAccountById方法并添加注解??
3.3.3 在測試類中測試??
* 立即查詢:查詢賬戶信息的同時查詢其用戶信息??
* @return??
*/??
@Select("select * from account")??
@Results(id="accountMap",value ={??
@Result(id = true,column = "id",property = "id"),??
@Result(column = "uid",property = "uid"),??
@Result(column = "money",property = "money"),??
@Result(column = "uid",property = "user",one = @One(??
select="com.itheima.dao.IUserDao.findById",??
fetchType = FetchType.EAGER//立即查詢??
)),??
})??
List<Account> findAllAccountAndUser();??
/**??
* 延時查詢:查詢用戶信息的同時查詢其所有賬戶信息??
*/??
@Select("select * from user")??
@Results(id="userMap",value = {??
@Result(id=true,column = "id",property = "id"),??
@Result(column = "username",property = "username"),??
@Result(column = "birthday",property = "birthday"),??
@Result(column = "sex",property = "sex"),??
@Result(column = "address",property = "address"),??
@Result(column = "id",property = "accounts",many = @Many(??
select="com.itheima.dao.IAccountDao.findAccountById",??
fetchType = FetchType.LAZY//延時查詢??
)),??
})??
List<User> findAllUserAndAccount();??
public interface IAccountDao {??
/**??
* 根據uid查詢對應的所有賬戶信息??
* @param uid??
* @return??
*/??
@Select("select * from account where uid=#{uid}")??
List<Account> findAccountById(int uid);??
}??
//立即查詢:查詢賬戶信息的同時查詢其用戶信息??
@Test??
public void findAllAccountAndUser(){??
List<Account> accounts = userDao.findAllAccountAndUser();??
//變量打印3.4 mybatis注解開發使用二級緩存??
3.4.1 在被測試的dao類上添加注解開啟二級緩存即可??
注意:SqlMapConfifig.xml中的中的??
cacheEnabled默認值就是true,可以不用配置。??
3.4.2 代碼測試??
mybatis擴展內容??
for (Account account : accounts) {??
System.out.println(account.getId()+"-"+account.getUid()+"-"+account.getMoney());??
System.out.println(account.getUser());??
}??
}??
//延時查詢:查詢用戶信息的同時查詢其所有賬戶信息??
@Test??
public void findAllUserAndAccount(){??
List<User> users = userDao.findAllUserAndAccount();??
for (User u : users) {??
System.out.println(u.getId()+"-"+u.getUsername()+"-"+u.getBirthday()+"-"+u.getSex()+"-??
"+u.getAddress());??
// System.out.println(u.getAccounts());??
}??
}??
//該接口查詢開啟二級緩存??
@CacheNamespace(blocking = true)??
public interface IUserDao {}??
//測試二級緩存??
@Test??
public void testSecondLeverCache(){??
//1.獲取第一個sqlSession對象并查詢user??
SqlSession session1 = factory.openSession(true);??
IUserDao userDao1 = session1.getMapper(IUserDao.class);??
User user1 = userDao1.findById(43);??
System.out.println("user1 = " + user1);??
//關閉session1??
session1.close();??
//2.獲取第二個sqlSession對象并查詢user??
SqlSession session2 = factory.openSession(true);??
IUserDao userDao2 = session2.getMapper(IUserDao.class);??
User user2 = userDao2.findById(43);??
System.out.println("user2 = " + user2);??
session2.close();??
//判斷user1和user2是不是同一個對象??
System.out.println("user1==user2 : " + (user1==user2));??
}1.mybatis使用第三方連接池??
1.1 mybatis中連接池原理??
1.2 使用第三方連接池步驟??
1.2.1 自定義工廠類實現mybatis的DataSourceFactory接口??
MyBatis 在初始化時,根據<dataSource>的 type 屬性來創建相應類型的的數據源 DataSource,即:??
type="POOLED": MyBatis 會創建 PooledDataSource 實例??
type="UNPOOLED": MyBatis 會創建 UnpooledDataSource 實例??
type="JNDI": MyBatis 會從 JNDI 服務上查找 DataSource 實例,然后返回使用??
當我們在<dataSource type="POOLED">配置POOLED時mybatis就會為我們創建PooledDataSource對象,這個對象是??
通過連接池工程創建出來的:??
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {??
public PooledDataSourceFactory() {??
this.dataSource = new PooledDataSource();??
}??
}??
public class UnpooledDataSourceFactory implements DataSourceFactory {??
//代碼省略??
}??
public interface DataSourceFactory {??
void setProperties(Properties props);??
DataSource getDataSource();??
}??
mybatis創建PooledDataSourceFactory工廠對象的同時會創建一個PooledDataSource連接池對象,然后調用工??
廠對象的setProperties(Properties props)方法將SqlMapConfig.xml中的連接池配置信息通過props傳遞進來,當??
進行CRUD操作時就調用getDataSource()方法獲取連接池對象。??
也就是說要想讓mybatis使用第三方連接池,我們就得自己定義一個工廠類,在工廠來中創建第三方連接池對象并??
在setProperties(Properties props)方法中設置連接參數,在getDataSource()方法中返回連接池對象??
package com.itheima.factory;??
import com.alibaba.druid.pool.DruidDataSource;??
import org.apache.ibatis.datasource.DataSourceFactory;??
import javax.sql.DataSource;??
import java.util.Properties;??
//DruidDataSourceFactory不是alibaba的DruidDataSourceFactory??
public class DruidDataSourceFactory implements DataSourceFactory {??
//聲明連接池對象??
private DruidDataSource dataSource;??
public DruidDataSourceFactory() {??
//創建連接池對象??
this.dataSource = new DruidDataSource();??
}??
@Override??
public void setProperties(Properties props) {??
//將SqlMapConfig.xml中的連接池配置信息設置給druid連接池對象??
dataSource.setDriverClassName(props.getProperty("driver"));1.2.2 在SqlMapConfifig.xml中使用第三方連接池??
1.2.3 在測試類中進行測試??
dataSource.setUrl(props.getProperty("url"));??
dataSource.setUsername(props.getProperty("username"));??
dataSource.setPassword(props.getProperty("password"));??
}??
@Override??
public DataSource getDataSource() {??
return dataSource;??
}??
}??
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"??
"http://mybatis.org/dtd/mybatis-3-config.dtd">??
??
resource="jdbcConfig.properties"/>??
??
name="com.itheima.domain"/>??
default="mysql">??
id="mysql">??
type="jdbc">??
type="com.itheima.factory.DruidDataSourceFactory">??
name="driver" value="${jdbc.driver}"/>??
name="url" value="${jdbc.url}"/>??
name="username" value="${jdbc.username}"/>??
name="password" value="${jdbc.password}"/>??
??
name="com.itheima.dao"/>??
2.mybatis查詢傳遞其他類型參數??
2.1 參數是Map集合??
在IUserDao.xml中配置查詢信息??
在測試類中測試??
//查詢所有操作??
@Test??
public void findAll(){??
//獲取連接池對象的名稱??
DataSource dataSource = session.getConfiguration().getEnvironment().getDataSource();??
System.out.println("dataSource = " + dataSource.getClass());//dataSource = class??
com.alibaba.druid.pool.DruidDataSource??
//查詢所有用戶信息??
List<User> users = userDao.findAll();??
for (User user : users) {??
System.out.println(user);??
}??
}??
id="findUserByMap" resultType="user"> select * from USER test="username!=null and username!=''"> and username like #{username} test="sex!=null and username!=''"> and sex = #{sex}??
//動態sql:根據map集合中的條件,查詢用戶信息??
@Test??
public void testFindUserByMap(){??
//創建Map集合并封裝查詢參數??
Map<String,Object> map=new HashMap<String,Object>();??
map.put("username","%王%");??
map.put("sex","女");??
//查詢符合條件的用戶信息??
List<User> users = userDao.findUserByMap(map);??
for (User user : users) {??
System.out.println(user);??
}??
}結論:使用map集合或者javabean對象作為參數,其實是一樣的,map集合對應的就是javabean的屬性。??
2.2 參數是List集合??
在IUserDao.xml中配置查詢信息??
在測試類中測試??
結論:mybatis其實是將參數list集合先存到map中,key為list(即map.pust("list",list集合對象)),所以??
collection="list"中的屬性值必須是list,就相當于從map中取出list遍歷??
2.3 參數是數組- 和參數是list幾乎一樣??
在IUserDao.xml中配置查詢信息??
id="findUserByList" resultType="user"> SELECT * FROM USER and id in( collection="list" item="id" separator=","> #{id} )??
//動態sql:查詢list集合中指定id的user信息??
@Test??
public void testFindUserByList(){??
//創建list集合并存儲要查的用戶id??
List<Integer> ids=new ArrayList<Integer>();??
ids.add(41);??
ids.add(43);??
ids.add(48);??
ids.add(50);??
//查詢符合條件的用戶信息??
List<User> users = userDao.findUserByList(ids);??
for (User user : users) {??
System.out.println(user);??
}??
}在測試類中測試??
結論:查詢參數是Array與查詢參數是list集合的原理是一樣的,都是現將對象存到map集合中,只不過參數??
為Array時,存到map集合中的key叫array,所以collection="array"的值必須是array??
2.4 多個參數情況以及@Param注解??
在IUserDao中定義查詢方法??
在IUserDao.xml中配置查詢信息??
id="findUserByArray" resultType="user"> SELECT * FROM USER and id in( collection="array" item="id" separator=","> #{id} )??
//動態sql:查詢數組中指定id的user信息??
@Test??
public void testFindUserByArray(){??
//創建list集合并存儲要查的用戶id??
Integer[] ids={41,43,48,50};??
//查詢符合條件的用戶信息??
List<User> users = userDao.findUserByArray(ids);??
for (User user : users) {??
System.out.println(user);??
}??
}??
/**??
* 多個參數:根據用戶名和性別查詢用戶信息??
* @Param("username") :定義參數的別名,將來在映射文件中使用??
*/??
public List<User> findUserByUsernameAndSex(@Param("username") String username,@Param("sex")??
String sex);??
}??
id="findUserByUsernameAndSex" resultType="user"> SELECT * FROM USER where username like #{username} and sex= #{sex} 在測試類中測試??
結論:最好是結果@Param注解一起使用,映射文件中#{username}使用的變量名就是 @Param("username")注解的參數值 3.mybatis注解開發-動態sql 3.1 方式1:在select注解中添加script腳本 在在IUserMapper方法上定義注解 測試類測試 /** * 多個參數:根據用戶名和性別查詢用戶信息 */ @Test public void testFindUserByUsernameAndSex(){ List<User> users = userDao.findUserByUsernameAndSex("%王%", "女"); for (User user : users) { System.out.println(user); } } /** * 動態sql:查詢list集合中指定id的user信息 */ @Select({""}) public List<User> findUserByList(List<Integer> ids); //動態sql:查詢list集合中指定id的user信息 @Test public void testFindUserByList(){ //創建list集合并存儲要查的用戶id List<Integer> ids=new ArrayList<Integer>(); ids.add(41); ids.add(43); ids.add(48); ids.add(50);總結:其實就是將xml映射文件中的配置拿過來用了,也是支持的。適用于帶in的查詢 3.1 方式2:字符串拼接(了解) 定義sql提供者UserMapperProvider類 在IUserMapper方法上定義注解 測試類測試 //查詢符合條件的用戶信息 List<User> users = userMapper.findUserByList(ids); for (User user : users) { System.out.println(user); } } /** * 為注解開發動態sql查詢提供sql */ public class UserMapperProvider { /** * 動態sql:根據map集合中的條件,查詢用戶信息 * @param map 查詢條件 * @return 根據條件返回sql */ public String findUserByMap(Map<String,Object> map){ StringBuilder sb=new StringBuilder("select * from user where 1=1 "); if(map.get("username")!=null){ sb.append(" and username like #{username}"); } if(map.get("sex")!=null){ sb.append(" and sex = #{sex}"); } return sb.toString(); } } public interface IUserMapper { /** * 動態sql:根據map集合中的條件,查詢用戶信息 */ @SelectProvider(type=UserMapperProvider.class,method = "findUserByMap") public List<User> findUserByMap(Map<String,Object> map); }3.2 方式3:使用mybatis中提供的SQL對象動態構建sql語句 修改UserMapperProvider提供者中的fifindUserByMap方法 4.mybatis使用Redis做二級緩存 總結 使用xml配置完成CURD操作 環境 jar包坐標 //動態sql:根據map集合中的條件,查詢用戶信息 @Test public void testFindUserByMap(){ //創建Map集合并封裝查詢參數 Map<String,Object> map=new HashMap<String,Object>(); map.put("username","%王%"); map.put("sex","女"); //查詢符合條件的用戶信息 List<User> users = userMapper.findUserByMap(map); for (User user : users) { System.out.println(user); } } public String findUserByMap(Map<String,Object> map){ return new SQL(){ //靜態代碼塊 { SELECT("*"); FROM("user"); if (map.get("username")!=null) { WHERE("username like #{username}"); } if (map.get("sex")!=null) { AND(); WHERE("sex = #{sex}"); } } }.toString(); } 配置文件 單表查詢 org.mybatis mybatis 3.4.5 mysql mysql-connector-java 5.1.38 junit junit 4.10 log4j log4j 1.2.12 測試多表查詢 一對多 多表查詢 多對多 使用annotation完成CURD操作 環境 與xml相同 單表查詢多表查詢 一對多