- 浏览: 1765156 次
- 性别:
- 来自: 大连
-
博客专栏
-
-
Spring数据库访问系列...
浏览量:174287
-
-
Android学习笔记
浏览量:369569
-
-
iBatis开发详解
浏览量:189900
-
-
Objective-C学习...
浏览量:100806
最新评论
-
iLidy:
引用[/c
Hibernate持久化对象的生命周期详解 -
fengzigogo:
您好,有这个项目架构的源码下载地址吗?
一种Java Web应用开发框架的构建(基于Struts2+Spring+FreeMarker)之一 -
spring_springmvc:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
用Maven构建Java Web开发环境(Jetty容器)之二 -
springdata_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring 3之MVC & Security简单整合开发(二) -
赵庆辉:
看帖回复是美德,楼主讲的很清晰明了,看了豁然开朗.
Java String对象的经典问题(new String())
CRUD操作中除了查询操作,其他都统一称为更新操作,因为增删改都是更新数据库表的,SqlMap API中对应的方法就是insert,update和delete,我们逐一来看。
insert方法的方法签名为:Object insert(String id, String parameterObject) throws SQLException。那么我们需要传递的参数就是XML文件中的映射语句名称和执行插入操作所需要的参数。返回值为Object类型,也就是说它可以返回一个对象。我们想想通过插入语句我们希望得到什么呢?没错,就是插入这条记录的主键。
这里还不得不多说一下主键的问题。虽然每种数据库都有自己主键的生成方式,但对于这种将数据插入到数据库后立即要知道主键的情况,就会产生问题。iBatis中的insert元素的一个子元素selectKey可以帮助我们获取自动生成的主键并保存在返回对象中,它有两种调用方式:
第一就是数据插入到数据库中之后立即抓取这条记录的主键的值,但此时要注意抓取的值确实是刚插入的记录的,也就是说数据库的驱动支持这么操作。如果有两个线程同时执行insert操作,其可能的顺序为insert #1,insert #2,selectKey #1,selectKey #2,那么在执行selectKey #1时得到的就是第二个记录的主键值了,这显然对程序产生了影响。
第二种方式就是在插入记录之前就获取键,然后连同这个键一同插入到数据库中,这样就不存在第一种情况的风险,是安全的操作。这种方式更倾向于支持序列的数据库。
在MySQL数据库中没有序列的支持,那么可以使用LAST_INSERT_ID()函数来获取自动生成的主键,我们来一段代码:
向数据库中插入一条记录同时获取了其生成的主键值,主键字段是userId,类型是int这都很好理解。而在程序中,我们只需这么来操作:
打印出的就是主键的值了,这个示例不但演示了iBatis的插入操作,也演示了插入操作同时获取主键值的方法,当然在Oracle中使用序列就行了,SQL Server是使用SCOPE_IDENTITY()函数,这参考一下数据库文档即可。
上面我们在执行更新操作时传递的参数是我们写好的ParameterMap类型,即:
这是内联参数映射的一种,当然我们也可以使用Javabean作为参数传递的对象,来看一个示例:
这样使用的前提是在User类中重载一个构造方法来传递属性的值,当然默认的构造方法也要有(当你调用了queryForObject()方法时)。另外一种是外部参数映射,我们定义一个parameterMap来测试这种情况:
自动生成的主键userId这里我们就不用写了,然后定义插入语句的映射:
最后在程序中,则和上面内联参数没有什么不同,除了映射的语句名称:
更新操作的第二种是update,SqlMap API中更新操作的方法签名是int update(String id, Object parameterObject) throws SQLException,参数的含义都已经非常清楚了,就是映射的语句名称和参数,而返回值是int型的。在JDBC规范中我们知道更新操作返回的是影响的结果行数,其实insert也是,只不过SqlMap给我们了新的选择。
要注意的一点是iBatis允许在一条SQL语句中更新一条或多条记录,而其他面向对象的工具是只允许修改一条记录(比如Hibernate),但Hibernate针对批量操作也做了处理。
说到批量操作,就会有并发的问题,那么事务机制很自然就要想到了,这里简单介绍一下iBatis处理批量操作的方法,后面会有详细介绍iBatis的事务。这里给出一个处理并发的小技巧,就是在高并发的数据表中加一个时间戳字段或者是版本字段控制,每次更新操作都修改这个字段,就能一定程度上控制数据完整性。
由于iBatis是SQL映射工具,那么就不需要像使用Hibernate那样考虑对象间的关系,在程序中做好处理就行了。先看下面这个示例:购物车订单,这是很经典的示例,我们需要建立两个类(订单和订单项),两个SQL映射文件和一个测试类。数据库表结构如下:
这是订单表,简单做示例,就订单名称和生成订单的时间两项即可。
这是订单项表,字段见名知意,这里就不多解释了。下面来看看实体类的设计:
下面是订单项的实体类,也很简单:
虽然iBatis是SQL映射,但是实体类中我们使用对象类型而不是基本数据类型还是有很多好处的,比如直接和null判断。下面我们来看SQL映射文件,其中使用了简单的动态SQL,这个后面会详细来说明。
分析一下这个配置,首先定义了Order类型,在文件中可以直接使用。然后就是SQL语句了,有添加,更新和删除操作,其中删除是删除所有的订单项,插入操作后返回自动生成的主键,这个在前面已经说明了,很好理解。那么订单项的配置文件就更简单了:
只有一个添加语句做示例。最后不要忘了在SqlMapConfig中引入这两个配置文件,下面来看看测试类:
代码能为我们完成任务,但是可以看出,这里没有任何的事务隔离,如果循环插入时发生了异常,那么数据完整性将遭到破坏。这是因为此时的事务是在每条语句执行时提交的,这也会影响程序的执行性能。做如下测试,修改main函数为:
一次测试时间是494,而如果:
执行时间可达到874,所以性能是很低的。下面我们来看看批量更新操作,将saveOrder()方法做如下修改:
测试出的运行时间是432,确实效率提高了,因为数据量小,不是很明显。这里要注意批量操作的开始地方,因为后面的OrderItem使用到了Order的主键,而这个主键是数据库自动生成的,那么我们必须获取到这个主键才能执行批量那个操作。而在executeBatch()执行时才会执行SQL操作,如果开始批量的位置不对,则不能获取到创建的主键的值,那么后面的操作也不能被执行了。
最后就是存储过程了,这里给出一个简单的示例:在存储过程中删除订单详细项,一个比较奇怪的地方就是iBatis调用mysql的存储过程要使用insert()方法,这里并不知道其原因。首先我们定义一个存储过程:
在SQL配置中,我们定义一个存储过程和映射参数类型:
程序中,使用insert()方法调用存储过程,比如:
除了存储过程,还有函数,我们也来看个示例:
这是MySQL的一个函数定义,在SQL映射文件中,必须使用select来标记,而不是procedure,这个要记住。
程序中,这样写就行了:
打印的结果就是7。至此iBatis的非查询语句就介绍完了。
那是动态SQL的一部分,用于判断字段逻辑而进行最终SQL的动态拼装
insert方法的方法签名为:Object insert(String id, String parameterObject) throws SQLException。那么我们需要传递的参数就是XML文件中的映射语句名称和执行插入操作所需要的参数。返回值为Object类型,也就是说它可以返回一个对象。我们想想通过插入语句我们希望得到什么呢?没错,就是插入这条记录的主键。
这里还不得不多说一下主键的问题。虽然每种数据库都有自己主键的生成方式,但对于这种将数据插入到数据库后立即要知道主键的情况,就会产生问题。iBatis中的insert元素的一个子元素selectKey可以帮助我们获取自动生成的主键并保存在返回对象中,它有两种调用方式:
第一就是数据插入到数据库中之后立即抓取这条记录的主键的值,但此时要注意抓取的值确实是刚插入的记录的,也就是说数据库的驱动支持这么操作。如果有两个线程同时执行insert操作,其可能的顺序为insert #1,insert #2,selectKey #1,selectKey #2,那么在执行selectKey #1时得到的就是第二个记录的主键值了,这显然对程序产生了影响。
第二种方式就是在插入记录之前就获取键,然后连同这个键一同插入到数据库中,这样就不存在第一种情况的风险,是安全的操作。这种方式更倾向于支持序列的数据库。
在MySQL数据库中没有序列的支持,那么可以使用LAST_INSERT_ID()函数来获取自动生成的主键,我们来一段代码:
<insert id="addUser" parameterClass="parameterMap" > insert into users(USERNAME,PASSWORD,AGE,MOBILE,EMAIL) values(#userName:VARCHAR#,#password:VARCHAR#,#age:INT#,#mobile:VARCHAR#,#email:VARCHAR#) <selectKey keyProperty="userId" resultClass="int"> select LAST_INSERT_ID() </selectKey> </insert>
向数据库中插入一条记录同时获取了其生成的主键值,主键字段是userId,类型是int这都很好理解。而在程序中,我们只需这么来操作:
ParameterMap parameterMap = new ParameterMap("userName", "sarin", "password", "123", "age", "23", "mobile", "1", "email", "@"); Object obj = sqlMap.insert("User.addUser", parameterMap); System.out.println(obj);
打印出的就是主键的值了,这个示例不但演示了iBatis的插入操作,也演示了插入操作同时获取主键值的方法,当然在Oracle中使用序列就行了,SQL Server是使用SCOPE_IDENTITY()函数,这参考一下数据库文档即可。
上面我们在执行更新操作时传递的参数是我们写好的ParameterMap类型,即:
package ibatis.util; import java.util.HashMap; public class ParameterMap extends HashMap<Object, Object> { private static final long serialVersionUID = 1L; public ParameterMap(Object... parameters) { for (int i = 0; i < parameters.length - 1; i += 2) { super.put(parameters[i], parameters[i + 1]); } } }
这是内联参数映射的一种,当然我们也可以使用Javabean作为参数传递的对象,来看一个示例:
User user = new User(null, "sarin", "123", "15940900000", "@", 23); Object obj = sqlMap.insert("User.addUser", user); System.out.println(obj);
这样使用的前提是在User类中重载一个构造方法来传递属性的值,当然默认的构造方法也要有(当你调用了queryForObject()方法时)。另外一种是外部参数映射,我们定义一个parameterMap来测试这种情况:
<parameterMap class="ibatis.util.User" id="userPramaterMap"> <parameter property="userName" jdbcType="VARCHAR" /> <parameter property="password" jdbcType="VARCHAR" /> <parameter property="age" jdbcType="INT" /> <parameter property="mobile" jdbcType="VARCHAR" /> <parameter property="email" jdbcType="VARCHAR" /> </parameterMap>
自动生成的主键userId这里我们就不用写了,然后定义插入语句的映射:
<insert id="addUserUseParameterMap" parameterMap="userPramaterMap"> insert into users(USERNAME,PASSWORD,AGE,MOBILE,EMAIL) values(?,?,?,?,?) <selectKey keyProperty="userId" resultClass="int"> select LAST_INSERT_ID() </selectKey> </insert>
最后在程序中,则和上面内联参数没有什么不同,除了映射的语句名称:
User user = new User(null, "sarin", "123", "15940900000", "@", 23); Object obj = sqlMap.insert("User.addUserUseParameterMap", user); System.out.println(obj);
更新操作的第二种是update,SqlMap API中更新操作的方法签名是int update(String id, Object parameterObject) throws SQLException,参数的含义都已经非常清楚了,就是映射的语句名称和参数,而返回值是int型的。在JDBC规范中我们知道更新操作返回的是影响的结果行数,其实insert也是,只不过SqlMap给我们了新的选择。
要注意的一点是iBatis允许在一条SQL语句中更新一条或多条记录,而其他面向对象的工具是只允许修改一条记录(比如Hibernate),但Hibernate针对批量操作也做了处理。
说到批量操作,就会有并发的问题,那么事务机制很自然就要想到了,这里简单介绍一下iBatis处理批量操作的方法,后面会有详细介绍iBatis的事务。这里给出一个处理并发的小技巧,就是在高并发的数据表中加一个时间戳字段或者是版本字段控制,每次更新操作都修改这个字段,就能一定程度上控制数据完整性。
由于iBatis是SQL映射工具,那么就不需要像使用Hibernate那样考虑对象间的关系,在程序中做好处理就行了。先看下面这个示例:购物车订单,这是很经典的示例,我们需要建立两个类(订单和订单项),两个SQL映射文件和一个测试类。数据库表结构如下:

这是订单表,简单做示例,就订单名称和生成订单的时间两项即可。

这是订单项表,字段见名知意,这里就不多解释了。下面来看看实体类的设计:
package ibatis.model; import java.util.Date; import java.util.List; public class Order implements java.io.Serializable { private Integer orderId; private String orderName; private java.util.Date generateTime; private List<OrderItem> orderItems; public Order() { } public Order(Integer orderId, String orderName, Date generateTime, List<OrderItem> orderItems) { super(); this.orderId = orderId; this.orderName = orderName; this.generateTime = generateTime; this.orderItems = orderItems; } // 省略getter和setter方法 @Override public String toString() { return "Order [generateTime=" + generateTime + ", orderId=" + orderId+ ", orderItems=" + orderItems + ", orderName=" + orderName+ "]"; } }
下面是订单项的实体类,也很简单:
package ibatis.model; public class OrderItem implements java.io.Serializable { private Integer oderItemId; private String itemName; private int quantity; private float price; private Integer orderId; public OrderItem() { } public OrderItem(Integer oderItemId, String itemName, int quantity, float price, Integer orderId) { super(); this.oderItemId = oderItemId; this.itemName = itemName; this.quantity = quantity; this.price = price; this.orderId = orderId; } // 省略getter和setter方法 @Override public String toString() { return "OrderItem [itemName=" + itemName + ", oderItemId=" + oderItemId+ ", orderId=" + orderId + ", price=" + price + ", quantity=" + quantity + "]"; } }
虽然iBatis是SQL映射,但是实体类中我们使用对象类型而不是基本数据类型还是有很多好处的,比如直接和null判断。下面我们来看SQL映射文件,其中使用了简单的动态SQL,这个后面会详细来说明。
<sqlMap namespace="Order"> <typeAlias alias="Order" type="ibatis.model.Order" /> <insert id="insert" parameterClass="Order"> insert into orders(orderName,generateTime) values (#orderName:VARCHAR#,now()) <selectKey keyProperty="orderId" resultClass="int"> select LAST_INSERT_ID() </selectKey> </insert> <update id="update" parameterClass="Order"> update orders set <dynamic> <isNotEmpty property="orderName"> orderName=#orderName:VARCHAR# </isNotEmpty> </dynamic> where orderId=#orderId:INT# </update> <delete id="deleteDetails" parameterClass="Order"> delete from orderitems where orderId=#orderId:INT# </delete> </sqlMap>
分析一下这个配置,首先定义了Order类型,在文件中可以直接使用。然后就是SQL语句了,有添加,更新和删除操作,其中删除是删除所有的订单项,插入操作后返回自动生成的主键,这个在前面已经说明了,很好理解。那么订单项的配置文件就更简单了:
<sqlMap namespace="OrderItem"> <typeAlias alias="OrderItem" type="ibatis.model.OrderItem" /> <insert id="insert" parameterClass="OrderItem"> insert into orderitems(itemName,quantity,price,orderId) values (#itemName:VARCHAR#,#quantity:INT#,#price:FLOAT#,#orderId:INT#) </insert> </sqlMap>
只有一个添加语句做示例。最后不要忘了在SqlMapConfig中引入这两个配置文件,下面来看看测试类:
package ibatis; // 省略包引入语句 public class OrderDemo { private static String config = "ibatis/SqlMapConfig.xml"; private static Reader reader; private static SqlMapClient sqlMap; static { try { reader = Resources.getResourceAsReader(config); } catch (IOException e) { e.printStackTrace(); } sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); } public static void main(String[] args) throws SQLException{ OrderItem item1 = new OrderItem(null, "IBM THINKPAD T410", 1, 10000, null); OrderItem item2 = new OrderItem(null, "HP 6930P", 1, 7000, null); OrderItem item3 = new OrderItem(null, "APPLE MC024", 1, 16000, null); // 创建OrderItem对象集合,放入三个购物项 List<OrderItem> orderItems = new ArrayList<OrderItem>(); orderItems.add(item1); orderItems.add(item2); orderItems.add(item3); Order order = new Order(null, "Sarin's Order", null, orderItems); saveOrder(sqlMap, order); } public static void saveOrder(SqlMapClient sqlMap, Order order) throws SQLException { // 判断是插入订单还是更新 if (null == order.getOrderId()) { sqlMap.insert("Order.insert", order); } else { sqlMap.update("Order.update", order); } // 清除订单原有信息 sqlMap.delete("Order.deleteDetails", order); // 插入订单项目 for (int i = 0; i < order.getOrderItems().size(); i++) { OrderItem oi = order.getOrderItems().get(i); oi.setOrderId(order.getOrderId()); sqlMap.insert("OrderItem.insert", oi); } } }
代码能为我们完成任务,但是可以看出,这里没有任何的事务隔离,如果循环插入时发生了异常,那么数据完整性将遭到破坏。这是因为此时的事务是在每条语句执行时提交的,这也会影响程序的执行性能。做如下测试,修改main函数为:
public static void main(String[] args) throws SQLException { long start = System.currentTimeMillis(); // 中间执行代码 long end = System.currentTimeMillis(); System.out.println(end - start); }
一次测试时间是494,而如果:
public static void main(String[] args) throws SQLException,IOException { long start = System.currentTimeMillis(); String config = "ibatis/SqlMapConfig.xml"; Reader reader= Resources.getResourceAsReader(config); SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); // 中间执行代码 long end = System.currentTimeMillis(); System.out.println(end - start); }
执行时间可达到874,所以性能是很低的。下面我们来看看批量更新操作,将saveOrder()方法做如下修改:
public static void saveOrder(SqlMapClient sqlMap, Order order) throws SQLException { // 开启事务 sqlMap.startTransaction(); try { // 判断是插入订单还是更新 if (null == order.getOrderId()) { sqlMap.insert("Order.insert", order); } else { sqlMap.update("Order.update", order); } // 开始批量操作 sqlMap.startBatch(); // 清除订单原有信息 sqlMap.delete("Order.deleteDetails", order); // 插入订单项目 for (int i = 0; i < order.getOrderItems().size(); i++) { OrderItem oi = order.getOrderItems().get(i); oi.setOrderId(order.getOrderId()); sqlMap.insert("OrderItem.insert", oi); } sqlMap.executeBatch(); sqlMap.commitTransaction(); } finally { sqlMap.endTransaction(); } }
测试出的运行时间是432,确实效率提高了,因为数据量小,不是很明显。这里要注意批量操作的开始地方,因为后面的OrderItem使用到了Order的主键,而这个主键是数据库自动生成的,那么我们必须获取到这个主键才能执行批量那个操作。而在executeBatch()执行时才会执行SQL操作,如果开始批量的位置不对,则不能获取到创建的主键的值,那么后面的操作也不能被执行了。
最后就是存储过程了,这里给出一个简单的示例:在存储过程中删除订单详细项,一个比较奇怪的地方就是iBatis调用mysql的存储过程要使用insert()方法,这里并不知道其原因。首先我们定义一个存储过程:

在SQL配置中,我们定义一个存储过程和映射参数类型:
<parameterMap class="java.util.Map" id="pm_delOiByOId"> <parameter property="orderId"/> </parameterMap> <procedure id="deleteOrderitemsByOrderId" parameterMap="pm_delOiByOId" resultClass="int"> call delete_orderitems_by_orderid(?) </procedure>
程序中,使用insert()方法调用存储过程,比如:
Map m = new HashMap(); m.put("orderId", 3); sqlMap.queryForObject("Order.deleteOrderitemsByOrderId", m);
除了存储过程,还有函数,我们也来看个示例:
CREATE DEFINER = `root`@`localhost` FUNCTION `max_in_example`(`a` int,`b` int) RETURNS int(10) BEGIN if(a > b) then return a; else return b; end if; END;
这是MySQL的一个函数定义,在SQL映射文件中,必须使用select来标记,而不是procedure,这个要记住。
<parameterMap class="java.util.Map" id="pm_in_example"> <parameter property="a"/> <parameter property="b"/> </parameterMap> <select id="in_example" parameterMap="pm_in_example" resultClass="int"> select max_in_example(?,?) </select>
程序中,这样写就行了:
Map m = new HashMap(2); m.put("a", new Integer(7)); m.put("b", new Integer(5)); Integer val = (Integer) sqlMap.queryForObject("User.in_example", m); System.out.println(val);
打印的结果就是7。至此iBatis的非查询语句就介绍完了。
评论
2 楼
sarin
2012-08-27
hellostory 写道
关于ibats更新update的书写方式,个人愚见:
为什么非得要“<isNotEmpty>”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。
为什么非得要“<isNotEmpty>”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。
那是动态SQL的一部分,用于判断字段逻辑而进行最终SQL的动态拼装
1 楼
hellostory
2012-08-27
关于ibats更新update的书写方式,个人愚见:
为什么非得要“<isNotEmpty>”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。
为什么非得要“<isNotEmpty>”才能更新字段呢?有这样一种情况,用户之前在备注字段写了一些信息,现在想把备注字段清空,那就没法实现了。
发表评论
-
iBatis操作DDL和映射继承
2012-09-09 21:46 9303本文系iBatis开发详解系列文章之iBatis操作D ... -
iBatis查询复杂集合
2012-09-04 20:23 15826本文系iBatis开发详解系列文章之在iBatis查询 ... -
iBatis中使用XML
2012-08-29 19:57 7747本文系iBatis开发详解系列文章之在iBatis中使 ... -
Spring数据库访问之iBatis(二)
2012-06-10 13:56 5849接上文,我们继续来研究Spring和iBatis的整合 ... -
Spring数据库访问之iBatis(一)
2012-01-02 18:45 16041为了丰富博客专栏【Spring数据库访问系列】的内容, ... -
我的视频教程《中小企业OA系统》
2011-07-29 22:27 7775经过5个月的制作,和华章合作的《中小企业OA系统》Ja ... -
iBatis分页(基于Struts2和Freemarker)
2011-05-02 10:05 13156之前介绍过基于Hibernate分页的原理和设计,这里 ... -
Spring数据库访问之ORM(三)
2011-03-02 20:35 17649本文接上一篇继续研究。 之前我们使用的是Hib ... -
Spring数据库访问之ORM(二)
2011-02-16 13:19 23436本文接上一篇继续来研究Spring的ORM模块。 ... -
Spring数据库访问之ORM(一)
2011-01-27 10:54 30909Spring数据库访问中另外一大模块就是ORM,ORM ... -
Spring数据库访问之异常处理
2011-01-19 10:29 27571使用JDBC API时,很 ... -
Spring数据库访问(HSQL)(四)
2011-01-16 21:49 14672本文接上一篇继续研究Spring的JDBC模板。 ... -
Spring数据库访问(HSQL)(三)
2011-01-13 10:07 13514本文接上一篇继续研究JDBC模板。 之前说的都 ... -
Spring数据库访问(HSQL)(二)
2011-01-11 11:27 10771上一篇我们介绍了 ... -
Spring数据库访问(HSQL)(一)
2011-01-09 23:34 13874本部分主要介绍Spring的JDBC模板,JDBC模板 ... -
Spring 3之MVC & Security简单整合开发(三)
2010-12-03 19:04 22161本文接上一篇继续深入研究Security框架。 ... -
Spring 3之MVC & Security简单整合开发(二)
2010-12-01 20:29 60207本文接上一篇继续 ... -
Spring 3之MVC & Security简单整合开发(一)
2010-11-30 22:00 42839Spring的MVC模块是一种简洁的Web应用框架,实 ... -
iBatis查询select详解
2010-08-07 12:19 40556<select>是iBatis已经映射的语 ... -
iBatis查询API
2010-07-31 13:04 17720先说点基础的内容 ...
相关推荐
IMG_20250415_160847.jpg
big_dripleaf_stem
内容概要:本文详细介绍了针对国内顶级科技公司(如华为、腾讯)的计算机求职面试内容与技巧。文章首先概述了技术能力考察的重点领域,包括数据结构与算法、操作系统、计算机网络、数据库以及特定编程语言的深入知识点。接着阐述了项目经验和系统设计方面的考察标准,强调了STAR法则的应用和具体的设计案例。此外,还分别描述了两家公司在面试流程上的不同之处,提供了具体的面试技巧,如代码编写的注意事项、项目回答的数据支持方法、系统设计的关键考量因素以及反问面试官的有效问题。最后,给出了避坑指南和资源推荐,帮助求职者更好地准备面试。 适合人群:即将或计划进入华为、腾讯等大型科技企业工作的应届毕业生和技术人员。 使用场景及目标:①帮助求职者了解并准备好技术面试所需的知识点;②指导求职者如何有效地展示自己的项目经验;③提供系统设计题目的解答思路;④传授面试过程中需要注意的行为规范和沟通技巧。 阅读建议:由于文中涉及大量专业知识和技术细节,建议读者在阅读时结合自身背景有选择地进行重点复习,并利用提供的资源链接进一步深化理解。同时,在准备过程中要注意将理论知识与实际操作相结合,多做练习以增强信心。
基于SpringBoot的课程设计选题管理系统,系统包含三种角色:管理员、用户,教师主要功能如下。 【用户功能】 系统首页:浏览课程设计选题管理系统的信息。 个人中心:管理个人信息,查看选题进展和历史记录。 课题信息管理:浏览已有的课题信息。 选题信息管理:查看已选择的选题信息。 自拟课题管理:提出和管理个人自拟的课题,。 系统管理:修改个人密码。 【管理员功能】 系统首页:查看系统整体概况。 个人中心:管理个人信息。 学生管理:审核和管理注册学生用户的信息。 教师管理:审核和管理注册教师用户的信息。 课题信息管理:监管和管理系统中的课题信息,包括发布、编辑、删除等。 课题分类管理:管理课题的分类信息。 选题信息管理:查看学生已选题目的情况,包括审批和管理选题流程。 自拟课题管理:审批和管理学生提出的自拟课题。 系统管理:管理系统的基本设置。 【教师功能】 系统首页:查看系统。 个人中心:管理个人信息。 课题信息管理:浏览已有的课题信息。 课题分类管理:管理课题的分类信息。 选题信息管理:查看学生已选题目的情况。 自拟课题管理:提出和管理个人自拟的课题。 系统管理:校园资讯管理。
橡胶履带牵引车辆改进设计(无极自动变速器方案设计).rar
剑桥大学发布的GVAR(Global Vector Autoregressive)数据集是用于全球宏观经济分析的重要社科数据资源。该数据集基于GVAR模型开发,旨在量化宏观经济发展对金融机构的影响,并分析全球经济互动。GVAR模型通过处理高维系统中的相互作用,解决了“维度诅咒”问题,适用于国家、地区、行业等多层次的经济分析。数据集包含1979-2016年33个国家的季度数据,可用于冲击情景分析、预测及政策评估。配套的GVAR工具箱(GVAR Toolbox)提供了用户友好的界面,支持MATLAB和Excel操作,便于研究人员开展实际应用。该数据集为经济学、金融学及相关领域的学术研究和政策制定提供了有力支持。
某汽车联合车间工艺布置图.zip
在stm32f407zgt上通过标准库实现w5500tcpserver和client,可以ping通速率不快
基于Python的微信跳一跳游戏程序
j
ElectLines.py
内容概要:本文档是一份针对Python测试开发工程师的算法能力测试卷,涵盖选择题、填空题、编程题和综合题四个部分。选择题考察Python基础知识、数据结构与算法、HTTP协议等;填空题涉及递归、排序、设计模式、HTTP请求方法、测试框架等具体知识点;编程题要求完成字符串反转、链表环检测、二叉树最大深度、两数之和及单元测试类的编写;综合题则包括设计自动化测试框架和实现测试报告生成器,旨在评估考生对Python编程和测试开发的全面掌握程度。 适合人群:具备Python编程基础,从事或计划从事测试开发工作的工程师。 使用场景及目标:①作为招聘流程中的技术考核工具;②帮助工程师自测和提升Python测试开发技能;③为企业内部培训提供标准化的评测标准。 阅读建议:此测试卷不仅考察语法和算法,更注重实际编程能力和解决问题的思路。建议考生在准备过程中多动手实践,熟悉常见的算法和数据结构,并掌握常用的测试框架和工具,如pytest、coverage等。同时,理解每个题目背后的设计意图,有助于更好地应对实际工作中的挑战。
一级减速器成套CAD图【22CAD】.rar
beetroots_stage2
IMG_20250415_104619.jpg
吴萌2262040206.zip
Android开发banner效果,用的是youthbanner的库,你们也可以去找原库demo
该资源为h5py-3.13.0-cp310-cp310-win_amd64.whl,欢迎下载使用哦!
内容概要:本文档提供了一个基于Python的贪吃蛇游戏完整代码示例。代码主要使用了Pygame库来创建游戏窗口、处理图形渲染与事件响应。游戏规则简单明了:玩家控制一条绿色的小蛇在黑色背景的游戏区域内移动,通过键盘方向键改变小蛇行进的方向,目的是吃到红色的食物方块使自身变长。当小蛇碰到边界或者自己的身体时,则判定为游戏失败并提示玩家选择是否重新开始或退出游戏。此外,还设置了帧率限制确保游戏流畅度。 适合人群:有一定Python编程基础的学习者,特别是对Pygame库感兴趣的开发者。 使用场景及目标:①作为初学者练习项目,帮助理解Pygame的基本用法;②可用于教学演示,讲解面向对象编程思想以及事件驱动机制;③为后续开发更复杂的游戏打下良好基础。 阅读建议:建议先熟悉Python语言特性及基本语法,再逐步深入研究本代码中的各个函数功能及其调用关系。同时可以尝试修改参数值(如窗口尺寸、颜色配置等),观察不同设置下的效果变化,从而加深对整个程序的理解。
birch_planks