• 第二章 MyBatis入门


    1.Junit的使用

            在maven中导入junit依赖:

    1. <dependency>
    2. <groupId>junitgroupId>
    3. <artifactId>junitartifactId>
    4. <version>4.11version>
    5. <scope>testscope>
    6. dependency>

    注解的用法: 

    @Test:表示一个可以独立运行的单元测试方法;

    @Before:在每个单元测试方法执行之前运行;

    @After:在每个单元测试方法之后运行;

    @BeforeClass:使用该注解的方法必须是静态方法,会在所有单元测试方法运行之前执行一次;

    @AfterClass:必须是静态方法,会在所有单元测试方法之后运行一次。

     2. MyBatis

    2.1 ORM思想

            ORM(对象关系映射 Object Relational Mapping)是通过描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。

    通过自定义注解和反射实现简单的orm:

    自定义注解:

    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Target(ElementType.FIELD)
    6. @Retention(RetentionPolicy.RUNTIME)
    7. public @interface ColumnInformation {
    8. String colName();
    9. String colType();
    10. int colSize() default 20;
    11. }
    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Target(ElementType.FIELD)
    6. @Retention(RetentionPolicy.RUNTIME)
    7. public @interface PrimaryKey {
    8. boolean isAutoIncrement();
    9. }
    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Target(ElementType.TYPE)
    6. @Retention(RetentionPolicy.RUNTIME)
    7. public @interface Table {
    8. String tableName();
    9. }

    给实体对象的添加注解:

    student:

    1. import com.wen.annotation.ColumnInformation;
    2. import com.wen.annotation.PrimaryKey;
    3. import com.wen.annotation.Table;
    4. import java.util.Date;
    5. @Table(tableName = "student")
    6. public class Student {
    7. @PrimaryKey(isAutoIncrement = true)
    8. @ColumnInformation(colName = "s_id",colType = "int",colSize = 11)
    9. private Integer s_id;
    10. @ColumnInformation(colName = "s_name",colType = "varchar",colSize = 10)
    11. private String s_name;
    12. @ColumnInformation(colName = "s_birth",colType = "date")
    13. private Date s_birth;
    14. @ColumnInformation(colName = "s_sex",colType = "char",colSize = 1)
    15. private String s_sex;
    16. public Student() {
    17. }
    18. public Student(Integer s_id, String s_name, Date s_birth, String s_sex) {
    19. this.s_id = s_id;
    20. this.s_name = s_name;
    21. this.s_birth = s_birth;
    22. this.s_sex = s_sex;
    23. }
    24. public Student(String s_name, Date s_birth, String s_sex) {
    25. this.s_name = s_name;
    26. this.s_birth = s_birth;
    27. this.s_sex = s_sex;
    28. }
    29. public Integer getS_id() {
    30. return s_id;
    31. }
    32. public void setS_id(Integer s_id) {
    33. this.s_id = s_id;
    34. }
    35. public String getS_name() {
    36. return s_name;
    37. }
    38. public void setS_name(String s_name) {
    39. this.s_name = s_name;
    40. }
    41. public Date getS_birth() {
    42. return s_birth;
    43. }
    44. public void setS_birth(Date s_birth) {
    45. this.s_birth = s_birth;
    46. }
    47. public String getS_sex() {
    48. return s_sex;
    49. }
    50. public void setS_sex(String s_sex) {
    51. this.s_sex = s_sex;
    52. }
    53. @Override
    54. public String toString() {
    55. return "Student{" +
    56. "s_id=" + s_id +
    57. ", s_name='" + s_name + '\'' +
    58. ", s_birth=" + s_birth +
    59. ", s_sex='" + s_sex + '\'' +
    60. '}';
    61. }
    62. }

    score:

    1. import com.wen.annotation.ColumnInformation;
    2. import com.wen.annotation.PrimaryKey;
    3. import com.wen.annotation.Table;
    4. @Table(tableName = "score")
    5. public class Score {
    6. @PrimaryKey(isAutoIncrement = true)
    7. @ColumnInformation(colName = "s_id",colType = "int",colSize = 20)
    8. private Integer s_id;
    9. @ColumnInformation(colName = "c_id",colType = "int",colSize = 20)
    10. private Integer c_id;
    11. @ColumnInformation(colName = "s_score",colType = "decimal",colSize = 3)
    12. private Double s_score;
    13. public Score() {
    14. }
    15. public Score(Integer s_id, Integer c_id, Double s_score) {
    16. this.s_id = s_id;
    17. this.c_id = c_id;
    18. this.s_score = s_score;
    19. }
    20. public Integer getS_id() {
    21. return s_id;
    22. }
    23. public void setS_id(Integer s_id) {
    24. this.s_id = s_id;
    25. }
    26. public Integer getC_id() {
    27. return c_id;
    28. }
    29. public void setC_id(Integer c_id) {
    30. this.c_id = c_id;
    31. }
    32. public Double getS_score() {
    33. return s_score;
    34. }
    35. public void setS_score(Double s_score) {
    36. this.s_score = s_score;
    37. }
    38. @Override
    39. public String toString() {
    40. return "Score{" +
    41. "s_id=" + s_id +
    42. ", c_id=" + c_id +
    43. ", s_score=" + s_score +
    44. '}';
    45. }
    46. }

    orm实现:

    inteeface:

    1. import java.util.List;
    2. import java.util.Map;
    3. public interface IGenericDao {
    4. /**
    5. * 查询全部数据
    6. * @param t
    7. * @return
    8. */
    9. List> listAll(T t);
    10. /**
    11. * 插入数据
    12. * @param t
    13. * @return
    14. */
    15. int insert(T t);
    16. /**
    17. * 修改数据
    18. * @param t
    19. * @return
    20. */
    21. int update(T t);
    22. /**
    23. * 删除数据
    24. * @param t
    25. * @return
    26. */
    27. int delete(T t);
    28. }

    impl:

    1. import com.wen.annotation.ColumnInformation;
    2. import com.wen.annotation.PrimaryKey;
    3. import com.wen.annotation.Table;
    4. import com.wen.orm.dao.IGenericDao;
    5. import com.wen.orm.util.BaseDao;
    6. import java.beans.IntrospectionException;
    7. import java.beans.PropertyDescriptor;
    8. import java.lang.reflect.Field;
    9. import java.lang.reflect.InvocationTargetException;
    10. import java.lang.reflect.Method;
    11. import java.util.List;
    12. import java.util.Map;
    13. public class GenericDaoImpl implements IGenericDao {
    14. private String getSql(Class t,String sign) {
    15. StringBuilder sql = new StringBuilder();
    16. if(t.isAnnotationPresent(Table.class)){
    17. Table table = (Table) t.getAnnotation(Table.class);
    18. Field[] declaredFields = t.getDeclaredFields();
    19. StringBuilder colSql = new StringBuilder();
    20. int count = 0;
    21. String colNameByPrimaryKey ="";
    22. switch (sign){
    23. case "selectAll":
    24. sql.append("select ");
    25. for (Field f:declaredFields) {
    26. ColumnInformation annotation = f.getAnnotation(ColumnInformation.class);
    27. colSql.append(annotation.colName()+",");
    28. }
    29. sql.append(colSql.substring(0,colSql.length()-1)).append(" from ").append(table.tableName());
    30. break;
    31. case "insert":
    32. sql.append("insert into ");
    33. sql.append(table.tableName());
    34. sql.append("(");
    35. for (Field f:declaredFields) {
    36. if(f.isAnnotationPresent(PrimaryKey.class)){
    37. continue;
    38. }
    39. ColumnInformation annotation = f.getAnnotation(ColumnInformation.class);
    40. colSql.append(annotation.colName()+",");
    41. count++;
    42. }
    43. sql.append(colSql.substring(0,colSql.length()-1));
    44. sql.append(") value (?");
    45. for (int i = 0; i < count-1; i++) {
    46. sql.append(",?");
    47. }
    48. sql.append(")");
    49. break;
    50. case "update":
    51. sql.append("update ");
    52. sql.append(table.tableName());
    53. sql.append(" set ");
    54. for (Field f:declaredFields) {
    55. ColumnInformation annotation = f.getAnnotation(ColumnInformation.class);
    56. if(f.isAnnotationPresent(PrimaryKey.class)){
    57. colNameByPrimaryKey = annotation.colName();
    58. continue;
    59. }
    60. colSql.append(annotation.colName()+"= ?,");
    61. }
    62. sql.append(colSql.substring(0,colSql.length()-1));
    63. sql.append(" where "+colNameByPrimaryKey+"= ?");
    64. break;
    65. case "delete":
    66. sql.append("delete from ");
    67. sql.append(table.tableName());
    68. for (Field f:declaredFields) {
    69. ColumnInformation annotation = f.getAnnotation(ColumnInformation.class);
    70. if(f.isAnnotationPresent(PrimaryKey.class)){
    71. colNameByPrimaryKey = annotation.colName();
    72. break;
    73. }
    74. }
    75. sql.append(" where "+colNameByPrimaryKey+"= ?");
    76. break;
    77. default:
    78. break;
    79. }
    80. }
    81. return sql.toString();
    82. }
    83. @Override
    84. public List> listAll(T t) {
    85. String sql = getSql(t.getClass(),"selectAll");
    86. System.out.println(sql);
    87. return BaseDao.executeQuery(sql,null);
    88. }
    89. @Override
    90. public int insert(T t) {
    91. Class aClass = t.getClass();
    92. String sql = getSql(aClass,"insert");
    93. System.out.println(sql);
    94. Field[] declaredFields = aClass.getDeclaredFields();
    95. Object[] params = new Object[declaredFields.length];
    96. int i = 0;
    97. for (Field field:declaredFields) {
    98. if(field.isAnnotationPresent(PrimaryKey.class)){
    99. continue;
    100. }
    101. try {
    102. PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), aClass);
    103. Method readMethod = propertyDescriptor.getReadMethod();
    104. params[i++] = readMethod.invoke(t);
    105. } catch (IntrospectionException e) {
    106. e.printStackTrace();
    107. } catch (IllegalAccessException e) {
    108. e.printStackTrace();
    109. } catch (InvocationTargetException e) {
    110. e.printStackTrace();
    111. }
    112. }
    113. System.out.println(i);
    114. Object[] newParams = new Object[i];
    115. System.arraycopy(params,0,newParams,0,i);
    116. for (Object o :newParams) {
    117. System.out.println(o);
    118. }
    119. return BaseDao.executeUpdate(sql,newParams);
    120. }
    121. @Override
    122. public int update(T t) {
    123. Class aClass = t.getClass();
    124. String sql = getSql(aClass,"update");
    125. System.out.println(sql);
    126. Field[] declaredFields = aClass.getDeclaredFields();
    127. Object oByPrimaryKey = "";
    128. Object[] params = new Object[declaredFields.length];
    129. int i = 0;
    130. for (Field f:declaredFields) {
    131. try {
    132. PropertyDescriptor propertyDescriptor = new PropertyDescriptor(f.getName(), aClass);
    133. if(f.isAnnotationPresent(PrimaryKey.class)){
    134. oByPrimaryKey = propertyDescriptor.getReadMethod().invoke(t);
    135. }else {
    136. params[i++] = propertyDescriptor.getReadMethod().invoke(t);
    137. }
    138. } catch (IntrospectionException e) {
    139. e.printStackTrace();
    140. } catch (IllegalAccessException e) {
    141. e.printStackTrace();
    142. } catch (InvocationTargetException e) {
    143. e.printStackTrace();
    144. }
    145. }
    146. params[i] = oByPrimaryKey;
    147. for (Object o: params) {
    148. System.out.println(o);
    149. }
    150. return BaseDao.executeUpdate(sql,params);
    151. }
    152. @Override
    153. public int delete(T t) {
    154. Class aClass = t.getClass();
    155. String sql = getSql(aClass,"delete");
    156. System.out.println(sql);
    157. Field[] declaredFields = aClass.getDeclaredFields();
    158. Object[] params = null;
    159. for (Field f:declaredFields) {
    160. if(f.isAnnotationPresent(PrimaryKey.class)){
    161. try {
    162. params = new Object[]{new PropertyDescriptor(f.getName(),aClass).getReadMethod().invoke(t)};
    163. } catch (IllegalAccessException e) {
    164. e.printStackTrace();
    165. } catch (InvocationTargetException e) {
    166. e.printStackTrace();
    167. } catch (IntrospectionException e) {
    168. e.printStackTrace();
    169. }
    170. }
    171. }
    172. System.out.println(params[0]);
    173. return BaseDao.executeUpdate(sql,params);
    174. }
    175. }

    测试:

    1. import com.wen.entity.Score;
    2. import com.wen.entity.Student;
    3. import com.wen.orm.dao.IGenericDao;
    4. import com.wen.orm.dao.impl.GenericDaoImpl;
    5. import java.text.ParseException;
    6. import java.text.SimpleDateFormat;
    7. import java.util.List;
    8. import java.util.Map;
    9. public class Test {
    10. public static void main(String[] args) throws ParseException {
    11. IGenericDao genericDao = new GenericDaoImpl();
    12. Student student = new Student();
    13. Score score = new Score(8,3,98.0);
    14. student.setS_id(15);
    15. student.setS_name("小温");
    16. student.setS_birth(new SimpleDateFormat("yyyy-MM-dd").parse("2008-1-1"));
    17. student.setS_sex("男");
    18. //genericDao.insert(student);
    19. //genericDao.insert(score);
    20. //genericDao.update(student);
    21. genericDao.delete(student);
    22. //genericDao.delete(score);
    23. System.out.println("======================");
    24. List> list = genericDao.listAll(student);
    25. for (Map map:list) {
    26. System.out.println(map);
    27. }
    28. }
    29. }

    2.2 MyBatis简介

            一个基于Java的持久层/数据访问层框架。

    2.3 结构

    ①接口层:给应用程序提供一系列的数据接口;

    ②接口层传递参数:sql命令,在数据处理曾进行处理,返回对应的结果映射;

    ③基础支撑层:提供最基础的底层的操作:连接管理(连接池),事务管理(增、删、该),配置加载(读取配置信息),缓存(一级缓存,二级缓存)

    2.4 环境搭建 

    整体结构:

     

            Mybatis官网:mybatis – MyBatis 3 | 入门

    ①建立maven项目,导入需要的jar包;

            pom.xml:

    1. <dependency>
    2. <groupId>org.mybatisgroupId>
    3. <artifactId>mybatisartifactId>
    4. <version>3.5.7version>
    5. dependency>
    6. <dependency>
    7. <groupId>mysqlgroupId>
    8. <artifactId>mysql-connector-javaartifactId>
    9. <version>8.0.11version>
    10. dependency>
    11. <dependency>
    12. <groupId>junitgroupId>
    13. <artifactId>junitartifactId>
    14. <version>4.11version>
    15. <scope>testscope>
    16. dependency>

    ②创建配置数据库连接信息的properties文件;

            db.properties:

    1. jdbc.driver = com.mysql.cj.jdbc.Driver
    2. jdbc.url = jdbc:mysql://127.0.0.1:3306/***?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    3. jdbc.userName =
    4. jdbc.password =

    ③配置数据库连接属性和mybati日志;

    Mybatis.xml:

    配置文件的属性是有序的,顺序不对会直接报错;

    1. configuration
    2. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    4. <configuration>
    5. <properties resource="db.properties">
    6. properties>
    7. <settings>
    8. <setting name="logImpl" value="STDOUT_LOGGING" />
    9. <setting name="mapUnderscoreToCamelCase" value="true"/>
    10. settings>
    11. <typeAliases>
    12. <typeAlias type="com.entity.Goods" alias="Goods"/>
    13. <package name="com.entity"/>
    14. typeAliases>
    15. <environments default="development">
    16. <environment id="development">
    17. <transactionManager type="JDBC"/>
    18. <dataSource type="POOLED">
    19. <property name="driver" value="${jdbc.driver}"/>
    20. <property name="url" value="${jdbc.url}"/>
    21. <property name="username" value="${jdbc.userName}"/>
    22. <property name="password" value="${jdbc.password}"/>
    23. dataSource>
    24. environment>
    25. environments>
    26. <mappers>
    27. <mapper class="com.mapper.GoodsMapper"/>
    28. mappers>
    29. configuration>

    ④在mapper包下创建对应实体的mapper接口(GoodsMapper.java)

     

    1. import com.entity.Goods;
    2. import com.entity.PageInfo;
    3. import java.util.List;
    4. import java.util.Map;
    5. public interface GoodsMapper {
    6. /**
    7. * 两表查询,包含商品种类
    8. * @return
    9. */
    10. List goodsList();
    11. /**
    12. * goods集合
    13. * @return
    14. */
    15. List listAllGoods();
    16. /**
    17. * 带分页的两表查询,含商品分类
    18. * pageInfo
    19. * @return
    20. */
    21. List goodsListByPage(PageInfo pageInfo);
    22. /**
    23. * 可一次插入多条商品记录
    24. * @param goodsList
    25. * @return
    26. */
    27. int insertGoods(List goodsList);
    28. /**
    29. * 单商品修改
    30. * @param goods
    31. * @return
    32. */
    33. int updateGoods(Goods goods);
    34. /**
    35. * 单商品删除
    36. * @param goodsId
    37. * @return
    38. */
    39. int deleteGoods(int goodsId);
    40. /**
    41. * 删库,重置自增列
    42. * @return
    43. */
    44. int cleanTable();
    45. }

    ⑤在mapper包下创建对应实体的mapper文件(GoodsMapper.xml)

    采用mapper接口开发的方式时,要注意:

    ①配置文件和其对应的接口,除了文件类型不同,其他的完全相同;

    ②resources中创建多级目录要用“/”来分割,不能用“.”;

    ③xml文件中对应的查询语句的"id"要与对应接口的方法名完全一致;

    ④返回的结果的类型或参数的类型,如果是自己创建的类型需要写完整,或者在MyBatis.xml中配置好别名;

    ⑤在sql语句中有多个参数时,名称要与传入的一致。

    1. mapper
    2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. <mapper namespace="com.mapper.GoodsMapper">
    5. <select id="goodsList" resultType="map">
    6. select goods_id,goods_name,price,produce_date,address,categoryName
    7. from tb_goods,category
    8. where tb_goods.category_id = category.categoryId
    9. select>
    10. <select id="listAllGoods" resultType="Goods">
    11. select goodsId,goodsName,price,produceDate,address,categoryId from goods
    12. select>
    13. <select id="goodsListByPage" resultType="map" parameterType="com.entity.PageInfo">
    14. select goods_id,goods_name,price,produce_date,address,category_id,categoryName
    15. from tb_goods,category
    16. where tb_goods.category_id = category.categoryId
    17. order by goods_id
    18. limit #{page},#{limit}
    19. select>
    20. <insert id="insertGoods" parameterType="java.util.ArrayList">
    21. insert into tb_goods(goods_name,price,produce_date,address,category_id)
    22. values
    23. <foreach collection="list" item="goods" index="index" separator=",">
    24. (#{goods.goodsName}, #{goods.price}, #{goods.produceDate}, #{goods.address}, #{goods.categoryId})
    25. foreach>
    26. insert>
    27. <delete id="deleteGoods">
    28. delete from tb_goods where goods_id = #{id}
    29. delete>
    30. <delete id="cleanTable">
    31. truncate tb_goods;
    32. delete>
    33. mapper>

    ⑥ 使用mybatis完成crud

    1. import com.dao.IGoodsDao;
    2. import com.entity.Goods;
    3. import com.entity.PageInfo;
    4. import com.mapper.GoodsMapper;
    5. import org.apache.ibatis.io.Resources;
    6. import org.apache.ibatis.session.SqlSession;
    7. import org.apache.ibatis.session.SqlSessionFactory;
    8. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    9. import java.io.IOException;
    10. import java.io.InputStream;
    11. import java.util.List;
    12. import java.util.Map;
    13. public class GoodsDaoImpl implements IGoodsDao {
    14. /**
    15. * 创建一个SqlSession的工厂用于创建sqlSession对象
    16. */
    17. private static SqlSessionFactory sessionFactory;
    18. static{
    19. try {
    20. InputStream resourceAsStream = Resources.getResourceAsStream("Mybatis.xml");
    21. sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    22. } catch (IOException e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. @Override
    27. public List goodsList() {
    28. SqlSession sqlSession = sessionFactory.openSession(true);
    29. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    30. List goodsList = mapper.goodsList();
    31. sqlSession.close();
    32. return goodsList;
    33. }
    34. @Override
    35. public PageInfo goodsListByPage(int page, int limit) {
    36. PageInfo pageInfo = new PageInfo();
    37. pageInfo.setPage((page-1)*limit);
    38. pageInfo.setLimit(limit);
    39. pageInfo.setTotalCount(goodsList().size());
    40. pageInfo.setTotalPage();
    41. SqlSession sqlSession = sessionFactory.openSession(true);
    42. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    43. List goodsList = mapper.goodsListByPage(pageInfo);
    44. sqlSession.close();
    45. pageInfo.setData(goodsList);
    46. return pageInfo;
    47. }
    48. @Override
    49. public int updateGoods(Goods goods) {
    50. SqlSession sqlSession = sessionFactory.openSession(true);
    51. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    52. int count = mapper.updateGoods(goods);
    53. sqlSession.close();
    54. return count;
    55. }
    56. @Override
    57. public int deleteGoods(int goodsId) {
    58. SqlSession sqlSession = sessionFactory.openSession(true);
    59. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    60. int count = mapper.deleteGoods(goodsId);
    61. sqlSession.close();
    62. return count;
    63. }
    64. @Override
    65. public int insertGoodsList(List goodsList) {
    66. SqlSession sqlSession = sessionFactory.openSession(true);
    67. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    68. int count = mapper.insertGoods(goodsList);
    69. sqlSession.close();
    70. return count;
    71. }
    72. @Override
    73. public int resetTable() {
    74. SqlSession sqlSession = sessionFactory.openSession(true);
    75. GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
    76. mapper.cleanTable();
    77. int count = mapper.insertGoods(mapper.listAllGoods());
    78. sqlSession.close();
    79. return count;
    80. }
    81. }

     ⑦mybatis的事务

    mybatis默认情况下是手动事务,在进行增删改操作之后要提交事务:

    ①提交:sqlSession.commit();

    ②设置自动事务:

            在MyBatis.xml中,修改transactionManager配置为:         

                    
                              
                    

            创建sqlSession时,openSession()设置为true,默认为false:              

                    sessionFactory.openSession(true)。

  • 相关阅读:
    Swing程序设计详解(一)
    同步锁synchronized追本溯源
    Util应用框架 UI 开发快速入门
    【使用 BERT 的问答系统】第 6 章 :BERT 模型应用:其他任务
    AM@第二类换元法积分
    Java毕设项目飞机订票管理系统计算机(附源码+系统+数据库+LW)
    MySQL字符集设置、密码管理
    AWS Lambda Golang HelloWorld 快速入门
    只有将公链无币化,才能支撑传统业务应用场景
    Python-Pychram使用
  • 原文地址:https://blog.csdn.net/m0_71674778/article/details/126335523