jpa、mybaties、jdbc

JDBC、mybaties、JPA的数据库开发

一、JDBC

1.概括

1.JDBC是Java访问数据库的标准规范,就是执行sql语句的javaAPI(Java语言通过JDBC可以操作数据库)

2.jdbc的由来,beacause

在这里插入图片描述

原因: 直接写代码操作数据库有以下问题

1.不知道MySql数据库的操作方式,解析方式;

2.代码非常繁琐,非常的麻烦;

3.MySQL和Oracle数据库的操作方式与解析方式不同、每个数据可都要写一套代码;

4,MySQL和Oracle数据库相互切换非常麻烦

现在
在这里插入图片描述
2.JDBC规范定义接口,具体的实现有个大数据库厂商来实现

JDBC是Java访问数据库的标准规范。真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用JDBC接口中的方法即可。数据库驱动由数据库厂商提供。

在这里插入图片描述

好处:1我们只需要调用JDBC接口中的方法使用简单;

2.使用通一套代码,进行少量修改就可以访问其他数据库;

2.1JDBC所用的包

  1. java.sql:JDBC访问数据库的基础包,在JavaSE中的包。如:java.sql.Connection
  2. javax.sql: JDBC访问数据库的扩展包
  3. 数据库的驱动,各大数据库厂商来实现。如:MySQL的驱动:com.mysql.jdbc.Driver

3.JDBC四个核心对象

  1. DriverManager: 用于注册驱动
  2. Connection: 表示与数据库创建的连接
  3. Statement: 执行SQL语句的对象
  4. ResultSet: 结果集或一张虚拟表

在这里插入图片描述

4.注册驱动使用步骤

	Class.forName("com.mysql.jdbc.Driver");
		
		// 连接到MySQL
		// url: 连接数据库的URL
		// user: 数据库的账号
		// password: 数据库的密码
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名", "root", "root");
		System.out.println(conn);//连接成功控制台显示  com.mysql.jdbc.JDBC4Connection@389177le(这个是连接对象connection)
	}

5.statement对象API介绍

  1. 1.boolean execute(String sql)
    //此方法可以执行任意sql语句。返回boolean值,表示是否返回ResultSet结果集。仅当执行select语句,且有返回结果时返回true, 其它语句都返回false;
    
  2. int executeUpdate(String sql)
    //根据执行的DML(INSERT、UPDATE、DELETE)语句,返回受影响的行数
    
  3. ResultSet executeQuery(String sql)
    //根据查询语句返回结果集,只能执行SELECT语句
    

注意:在MySQL中,只要不是查询就是修改。

executeUpdate:用于执行增删改

executeQuery:用于执行查询

6.代码演示

public class StatementDemo {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");

		Connection conn = DriverManager.getConnection("jdbc:mysql:///num1?			characterEncoding=utf8", "root", "root");
		System.out.println(conn);

		// String sql = "SELECT * FROM category;";
		// 从连接中拿到一个Statement对象
		Statement stmt = conn.createStatement();

		// 1.插入记录
		String sql = "INSERT INTO category (cname) VALUES ('手机');";
		int i = stmt.executeUpdate(sql);
		System.out.println(  i);

		// 2.修改记录
		sql = "UPDATE category SET cname='汽车' WHERE cid=4;";
		i = stmt.executeUpdate(sql);
		System.out.println(i);

		// 3.删除记录
		sql = "DELETE FROM category WHERE cid=1;";
		i = stmt.executeUpdate(sql);
		System.out.println(i);
	
		// 释放资源
		stmt.close();
		conn.close();
	}
}

6.数据库对于表的查询

ResultSet用于保存执行查询SQL语句的结果。
我们不能一次性取出所有的数据,需要一行一行的取出。
ResultSet的原理:
1. ResultSet内部有一个指针,刚开始记录开始位置
2. 调用next方法, ResultSet内部指针会移动到下一行数据
3. 我们可以通过ResultSet得到一行数据 getXxx得到某列数据

ResultSet获取数据的API

其实ResultSet获取数据的API是有规律的get后面加数据类型。我们统称getXXX()
在这里插入图片描述

7.使用JDBC查询数据库中的数据的步骤

Class.forName("com.mysql.jdbc.Driver");
		
		Connection conn = DriverManager.getConnection("jdbc:mysql:///num1", "root", "root");
		Statement stmt = conn.createStatement();
		
		String sql = "SELECT * FROM student;";
		ResultSet rs = stmt.executeQuery(sql);
		
		// 内部有一个指针,只能取指针指向的那条记录
		while (rs.next()) { // 指针移动一行,有数据才返回true
			// 取出数据
			int cid = rs.getInt("cid");
			String cname = rs.getString("cname");
          	String habby = rs.getString("habby")
			
			System.out.println("id: " +cid + "==" + "name: "+name+"=="+"habby: "+habby);
		}
		
		// 关闭资源
		rs.close();
		stmt.close();
		conn.close();
	}

总结:其实我们使用JDBC操作数据库的步骤都是固定的。不同的地方是在编写SQL语句

  1. 注册驱动
  2. 获取连接
  3. 获取到Statement
  4. 使用Statement执行SQL
  5. ResultSet处理结果
  6. 关闭资源

8.JDBC操作事物使用步骤

  1. 注册驱动
    2. 获取连接
    3. 获取到Statement
    4. 开启事务
    5. 使用Statement执行SQL
    6. 提交或回滚事务
    7. 关闭资源

8.1代码实现

	public static void main(String[] args) {
		Connection conn = null;
		try {
			// 拿到连接
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql:///num1", "root", "root");
			
			// 开启事务
			conn.setAutoCommit(false);
			
			Statement pstmt = conn.createStatement();
			
			// 老王减500
			String sql = "UPDATE account SET balance = balance - 500 WHERE id=1;";
			pstmt.executeUpdate(sql);
			// 模拟异常
			// int i = 10 / 0;
			
			// 老关加500
			sql = "UPDATE account SET balance = balance + 500 WHERE id=2;";
			pstmt.executeUpdate(sql);
			
			pstmt.close();
			// 成功,提交事务
			System.out.println("成功,交互成功");
			conn.commit();
		} catch (Exception e) {
			// 失败,回滚事务
			try {
				System.out.println("出了异常,回滚事物,出错");
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

二、mybaties

1.概述

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation
迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
作为持久层的框架,还有一个封装程度更高的框架就是Hibernate,但这个框架因为各种原因目前在国内的流行程度下降太多,现在公司开发也越来越少使用。
1.mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而且不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
2.mybatis 通过 xml或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为
java 对象并返回。
3.采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
(orm是对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换
。从效果上说,它其实是创建了一个可在编程语言里使用的–“虚拟对象数据库”。)

1.1mybaties对比jdbc优势

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
2、Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变Java代码。
3、使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

2.mybaties实现dao开发方式

mapper实现方式

Mapper 接口开发方法只需要程序员编写 Dao 接口,由 Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同
Dao 接口实现类方法。

1、 Mapper.xml 文件中的 namespace 与 Dao接口的类路径相同。

2、 Dao接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同

3、 Dao接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同

4、 Dao接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同

<dependencies>
      <dependency>
 			<groupId>org.mybatis</groupId>
 			<artifactId>mybatis</artifactId>
			 <version>3.4.5</version>
 </dependency>
 <dependency>
 			<groupId>junit</groupId>
			 <artifactId>junit</artifactId>
 			<version>4.10</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 			<groupId>mysql</groupId>
			 <artifactId>mysql-connector-java</artifactId>
			 <version>5.1.6</version>
 <scope>runtime</scope>
 </dependency>
 <dependency>
 			<groupId>log4j</groupId>
 			<artifactId>log4j</artifactId>
			<version>1.2.12</version>
 </dependency>
 </dependencies>

SqlSessionConfig.xml配置文件顺序

properties(属性) 导入 .properties 内容

settings(全局配置参数) 懒加载的时候用

typeAliases(类型别名)

为某个java类起名 ,配置别名:在MyBatis中为一个类取别名 配置别名是为了在对象映射文件中接收参数类型和返回参数类型时使用

<typeAlias alias="Product" type="cn.itsource.domain.Product"/> </typeAliases>
<!--alias:取的别名
    type:这个别名所对应的Java类   默认是类名小写     别名使用的时候与大小写无关    -->

typeHandlers(类型处理器)

objectFactory(对象工厂)

MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。
默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。
如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。

plugins(插件)

简单理解为拦截器,既然是拦截器说白了一般都是动态代理来实现对目标方法的拦截,在前后做一些操作。

environments(环境集合属性对象)

首先获取标签元素的default属性,这个属性作用就是指定当前情况下使用哪个数据库配置,也就是使用哪个节点的配置,default的值就是配置的标签元素的id值。

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

用来在mybatis初始化的时候,告诉mybatis需要引入哪些Mapper映射文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            	  <property name="driver" value="${jdbc.driver}"/>
				 <property name="url" value="${jdbc.url}"/>
				 <property name="username" value="${jdbc.username}"/>
				 <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--建立主配置文件和sql映射文件的关系-->
    <mappers>
        <mapper resource="ContactDaoMapper.xml"/>
    </mappers>
</configuration>

mapper配置文件

<!--//Mybatis 的映射文件其实就是与 DAO 相对应,因为 DAO 中的方法有输入参数及返回结果,那么在
Mybatis 的映射文件中自然也就有与之对应的参数和返回结果。-->

<!--1、 Mapper.xml 文件中的 namespace 与 Dao接口的类路径相同。

	2、 Dao接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同

	3、 Dao接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
 -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    namespace 名称空间 必须唯一 每一个Dao都会配置一个名称空间
    使用全限定类名 配置到接口即可
  -->

<mapper namespace="com.jiangrongxin.dao.ContactDao">
    <!--
        select标签用于查询  id表示 方法的名称
        resultType 返回结果的类型
     -->
    <select id="selectFindContact" resultType="com.jiangrongxin.pojo.Contact">
        select * from Contact
    </select>
  
  <!--parameterType参数类型-->
    <insert id="saveContact" parameterType="com.jiangrongxin.pojo.Contact">
        /*获取主键*/
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
     INSERT INTO contact(name,sex,age,address,qq,email) VALUES (#{name},#{sex},#{age},#			{address},#{qq},#{email})
    </insert>

    <update id="updateContact" parameterType="com.jiangrongxin.pojo.Contact">
        update contact set  name=#{name} , sex=#{sex}, age=#{age}, address=#{address}, qq=#{qq}, email=#{email} where id=#{id}
    </update>
   
  <delete id="deleteContactById" parameterType="com.jiangrongxin.pojo.Contact">
        delete   from contact where id = #{id}
    </delete>

</mapper>
<!--我们可以发现,这个 sql 语句中使用#{}字符,#{}代表占位符, 具体的值是由 Contcat 类的 name 属性来决定的。
parameterType 属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
注意:
这 种 方 式 要 求 <mapper names -->

Contact实体类

    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    private String address;
    private Integer qq;
    private String email;

持久层接口ContactDao

public interface ContactDao {
     List<Contact> selectFindContact();

     int saveContact(Contact contact);

     int updateContactById(Contact contact);

     int deleteContactById(Integer id);
}

测试类test

 public static void main(String[] args) {
       
    private InputStream res;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory build;
    private SqlSession sqlSession;
    private ContactDao mapper;

    @Before
    public void before() {
        try {
          //加载配置文件
            res = Resources.getResourceAsStream("SqlSessionConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        builder = new SqlSessionFactoryBuilder();
        //构建sqlsession工厂
        build = builder.build(res);
        //sqlSession 相当于connection
        // session 会话  指 程序和数据库的连接 底层封装的就是connection的操作
        sqlSession = build.openSession();
        mapper = sqlSession.getMapper(ContactDao.class);
    }
    @After
    public void test5(){
        //mybaties  事物是默认开启的必须要提交
        sqlSession.commit();
    }

    @Test
    public void test1() {
        List<Contact> contact = mapper.selectFindContact();
        for (Contact contact1 : contact) {
            System.out.println(contact1);
        }

    }
   
    @Test
    public void test() {
        Contact contact = new Contact("关某", "男", 11, "天安门", 111111, "1111@163.com");
        int i = mapper.saveContact(contact);
        System.out.println(i);

        //查询主键ID
        Integer id = contact.getId();
        System.out.println(id);
        System.out.println(i);
    }
        //修改
    @Test
    public void test3(){
        Contact contact = new Contact();
        contact.setId(29);
        contact.setAge(14);
        int i = mapper.updateContactById(contact);
        System.out.println(i);

    }
    //删除
    @Test
    public void test4() {

        int i = mapper.deleteContactById(2);

        System.out.println(i);


    }

2.1resultMap

如果数据库列名与实体类的属性不一致时,我们就不能封装结果集(resultType)到指定的实体对象。

<--过改别名的方式,现在返回结果集的列名已经与 User 类的属性名不相同了。-->
  	
  <select id="findAllUser" resultMap="userMap" >
        select id id , username name ,age  a,gender  g from USER
    </select>
<resultMap id="userMap" type="com.jrx.pojo.User">
        <!--1.特殊属性 主键-->
        <id column="id" property="id"></id>
        <!--2.普通属性 其他的属性-->
        <result column="name" property="username"></result>
        <result column="g" property="gender"></result>
        <result column="a" property="age"></result>
    </resultMap>
  <!--
        resultMap 结果的map集合
            id="" 给结果唯一的一个标识
            type="" 类型 相当于 resultType 就是封装之后的结果对象
            autoMapping="true"  自动映射 将匹配的属性自动通过set方法 或者 属性名称 赋值
            <id></id> 专门用来匹配主键
                 column=""  列 数据库真实查询的列名
                 property="" 属性
            <result></result> 专门用来匹配其他属性
             select id id , username name ,age  a,gender  g from USER
    -->

2.2Mybatis 代理方式实现 DAO 源码分析

getMapper(Class<T> type, SqlSession sqlSession) 
protected T newInstance(MapperProxy<T> mapperProxy) {
 return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),
                                   new Class[] { mapperInterface }, mapperProxy);
 }
//当调用方法时,会去调用 MapperProxy 的 invoke()方法;
//这个 invoke()的最后一行: 
return mapperMethod.execute(sqlSession, args);
//继续往下找这个方法:execute(sqlSession, args);
下面是它的方法体
Object result;
 switch (command.getType()) {
 case INSERT: {
 Object param = method.convertArgsToSqlCommandParam(args);
 result = rowCountResult(sqlSession.insert(command.getName(), param));
 break;
 }
 case UPDATE: {
 Object param = method.convertArgsToSqlCommandParam(args);
 result = rowCountResult(sqlSession.update(command.getName(), param));
 break;
 }
 case DELETE: {
 Object param = method.convertArgsToSqlCommandParam(args);
 result = rowCountResult(sqlSession.delete(command.getName(), param));
 break;
 }
 case SELECT:
 if (method.returnsVoid() && method.hasResultHandler()) {
 executeWithResultHandler(sqlSession, args);
 result = null;
 } else if (method.returnsMany()) {
 result = executeForMany(sqlSession, args);
 } else if (method.returnsMap()) {
 result = executeForMap(sqlSession, args);
 } else if (method.returnsCursor()) {
 result = executeForCursor(sqlSession, args);
 } else {
 Object param = method.convertArgsToSqlCommandParam(args);
 result = sqlSession.selectOne(command.getName(), param);
 }
 break;
 case FLUSH:
 result = sqlSession.flushStatements();
 break;
 default:
 throw new BindingException("Unknown execution method for: " + 
command.getName());
 }

2.3映射文件动态方式

1.if

<select id="findContcatByName" resultType="Contcat">
        select * from user where 1=1
         <if test="name != null and name != ''">
              and username like #{username}
         </if>
 </select>

2.foreach

<!-- 可以传入多个id 查询多条语句
 collection="数组" 遍历的集合 普通类型的情况下
            item=""  变量
            open=""     开始  sql+= " ( ";
            close=""    结束  sql+= " ) ";
            separator="" 分割  ",";
            拼接之后的sql语句
                select * from contact where id in ( #{id} ,#{id} ,#{id} , #{id} )-->
 <select id="findContcatByIdsArray" resultType="user" parameterType="int[]">
        select * from user where id in
        
   <foreach collection="array" item="id" open="(" close=")" separator="," >
          
     #{id}
       
   </foreach>

</select>

3.mybaties延迟加载

延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

坏处:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--引入外部的一个db.properties配置文件 支持el-->
    <properties resource="db.properties"></properties>

    <settings>
        <!--懒加载配置-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <typeAliases>
        <!--配置到包下即可  包下的所有的类自动起别名  别名就是类名 不区分大小写 -->
        <package name="com.jrx.pojo"></package>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--建立关系-->
        <package name="com.jrx.dao"></package>
    </mappers>
</configuration>

dao

public interface AccountDao {
    List<Account> findAllSelect();
}

pojo

public class Account {
    private Integer id;
    private Integer uid;
    private String  money ;
    private User user;
}

public class User {
    private String id;
    private String username;
    private String age;
    private String sex;
    private String address;
}

test

//多表查询
 //懒加载全查
    @Test
    public void test4(){
        AccountDao mapper = sqlSession.getMapper(AccountDao.class);
        List<Account> allSelect = mapper.findAllSelect();
        for (Account account : allSelect) {
            System.out.println(account);
        }
    }


/*结果:2019-04-06 22:08:16,316 537    [           main] DEBUG t.dao.AccountDao.findAllSelect  - ==>  Preparing: select * from account 
2019-04-06 22:08:16,341 562    [           main] DEBUG t.dao.AccountDao.findAllSelect  - ==> Parameters: 
2019-04-06 22:08:16,390 611    [           main] DEBUG t.dao.AccountDao.findAllSelect  - <==      Total: 3
2019-04-06 22:08:16,391 612    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - ==>  Preparing: select *from user where id =? 
2019-04-06 22:08:16,391 612    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - ==> Parameters: 41(Integer)
2019-04-06 22:08:16,394 615    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - <==      Total: 1
Account{id=1, uid=41, money='1000', user=User{id='41', username='老王', age='null', sex='男', address='北京王府井'}}
2019-04-06 22:08:16,394 615    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - ==>  Preparing: select *from user where id =? 
2019-04-06 22:08:16,394 615    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - ==> Parameters: 45(Integer)
2019-04-06 22:08:16,397 618    [           main] DEBUG m.jrx.dao.UserDao.findAllId  - <==      Total: 1
Account{id=2, uid=45, money='1000', user=User{id='45', username='小刘', age='null', sex='男', address='北京王府井'}}
Account{id=3, uid=41, money='2000', user=User{id='41', username='老王', age='null', sex='男', address='北京王府井'}}*/

只查一个数据

	@Test
    public void test5(){
        AccountDao mapper = sqlSession.getMapper(AccountDao.class);
        List<Account> allSelect = mapper.findAllSelect();

        for (Account account : allSelect) {
            System.out.println(account.getId());
        }
    }



/*结果

2019-04-06 22:10:44,984 522    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1971851377.
2019-04-06 22:10:44,984 522    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@75881071]
2019-04-06 22:10:44,986 524    [           main] DEBUG t.dao.AccountDao.findAllSelect  - ==>  Preparing: select * from account 
2019-04-06 22:10:45,011 549    [           main] DEBUG t.dao.AccountDao.findAllSelect  - ==> Parameters: 
2019-04-06 22:10:45,055 593    [           main] DEBUG t.dao.AccountDao.findAllSelect  - <==      Total: 3
1
2
3
*/

4.注解开发

public interface UserDao {
    @Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void saveUser(User user);

    @Update("update user set address = #{address} ,sex = #{sex}  where  username = #{username}")
    void upDate(User user);


    @Delete("delete from user where id=#{id}")
    void deleteUser(User user);

    @Select("select *from user")
    List<User> selectList();
  
  
  
    /*
    *  @Result(
    *  property = "user" 封装数据到哪个属性
     *  ,javaType = User.class 返回值的类型
     *  column = "uid" 调用方法时 传递的参数
      *  )
      *  @One 一张表对一张表
      *     select ="" 查询 定位到sql即可  全限定类名.方法名称
      *     fetchType = "" 抓取类型 调用查询用户方法的时机
      *     FetchType.LAZY  懒加载  全局配置true
    * */
 	 @Select("select * from account")
    @Results(value={
            @Result(id = true , column = "id" , property = "id"),
            @Result(column = "money" , property = "money"),
            /*配置外键*/
            @Result(property = "user" ,javaType = User.class , column = "id",
                    one = @One(select ="com.itheima.dao.UserDao.findUserById" , fetchType = 	FetchType.LAZY) )
    })
    List<Account> findAllAccountAndUser();

三、JPA

1.概述

JPA 的全称是 Java Persistence API(java持久化语言),是 SUN 公司推出的一套基于 ORM
的规范(接口),内部是由一系列的接口和抽象类构成;

ORM通过编程的方式将对象类型转换成关系类型。主要特点是将object映射成数据库中的数据。

2.实现

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- hibernate 对 jpa 的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- log 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Mysql and MariaDB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>

配置文件

<?xml version="1.0" encoding="UTF-8"?>  
<persistence xmlns="http://java.sun.com/xml/ns/persistence"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"  
    version="2.0">

    <!--
        persistence-unit:设置持久化单元
            name属性:设置持久化单元名称
            transaction-type: 事务类型
                RESOURCE_LOCAL 本地事务
                JTA 分布式事务
    -->
    <persistence-unit name="jpaUnit" transaction-type="RESOURCE_LOCAL">
        <!--指定JPA实现的提供商,可以不写-->
        <!--<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>-->
        <!--指定类的全路径名,可以不写-->
       <!-- <class>pojo.Customer</class>-->
        <properties>
            <!--数据库连接-->
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.url" value="jdbc:mysql:///day01"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value="root"/>

            <!--数据库方言-->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>

            <!--显示sql语句-->
            <property name="hibernate.show_sql" value="true"/>
            <!--格式化sql-->
            <property name="hibernate.format_sql" value="true"/>
            <!--hbm2ddl -->
            <!--update : 有表就直接使用,没有就创建-->
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

pojo

@Entity //声明实体类
@Table(name="cst_customer")
//建立类与表的映射关系。如果类名和表名一致,则此注解可以不写
public class Customer  {
    @Id //建立与表中主键的映射关系
    @Column(name = "cust_id")  //建立属性名与表中字段的映射关系。标的列名和字段名一样,就不用写 
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //对应AUTO_INCREMENT
    @Column(name = "cust_name")
    private String custName;

    @Column(name = "cust_source")
    private String custSource;

    @Column(name = "cust_industry")
    private String custIndustry;

    @Column(name = "cust_level")
    private String custLevel;

    @Column(name = "cust_address")
    private String custAddress;

    @Column(name = "cust_phone")
    private String custPhone;
}

jpa 工具类

private static EntityManagerFactory managerFactory;
    static{
        //创建实体类管理器工厂(相当于连接池)
        managerFactory = Persistence.createEntityManagerFactory("jpaUnit");
    }
    //获得连接
    public static EntityManager getEntityManager(){
        return managerFactory.createEntityManager();
    }

test

private  EntityManager em;
private EntityTransaction tx

@Before
public void before(){
	// 获取实体管理对象
	em=  JPAUtil.getEntityManager();
	// 获取事务对象
    tx=em.getTransaction();
    // 开启事务
     tx.begin();
}
@After
public void after(){
        tx.commit();
        em.close();
}
//增加
@test
public void test(){
  Customer c = new Customer();
        c.setCustName("中国社会科学院");
        c.setCustAddress("王府井甲一号");      
		em.persist(c);
}
	//查询
 	@Test
    public void test2(){
        Customer c = em.find(Customer.class, 1L);
        System.out.println(c);
        
    }

    @Test
    public void test3(){
        Customer c = em.find(Customer.class, 1L);
        c.setCustName("中国社会最厉害科学院");
        em.merge(c);//修改合并
    }
	//删除
    @Test
    public void test4(){
      
        Customer c = em.find(Customer.class, 1L);
        em.remove(c);
    }
    //条件查询
    public void test5 () {
    String jpql = "from Customer where custName like ? ";
    Query query = em.createQuery(jpql);
	//对占位符赋值,从 1 开始
	query.setParameter(1, "科学大牛%");
	//查询并得到返回结果
	Object object = query.getSingleResult(); //得到唯一的结果集对象
	System.out.println(object);
	
    
    
    }

总结

1.JDBC是较底层的持久层操作方式,它的的工作量比较大,需要连接,然后处理jdbc底层事务,处理数据类型,还需要操作Connection,Statement对象和ResultSet对象去拿数据并关闭他们,所以用的少;

2.mybaties 比jdbc操作简单 ,代码量减少了一半以上,而且SQL写在XML里,从程序代码中彻底分离,降低耦合度,MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

3.jpa最主要的特点就是使用简单。JPA底层使用关系数据库进行存储,因此具备关系数据库的特点,例如事务性、数据完整性、并发访问、大数据量等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值