For example:
Let's say there is a Texture2D class, that is used to refer to textures stored on the GPU. The problem is: storing the specific GLuint (or whatever the alternative for DX is) within the Texture2D object directly, which would make my code very dependent to OpenGL.
RED ALERT.
The very first step to abstracting across APIs is being familiar with several of them. You apparently are not. The very first step to writing abstract code is understanding what is being abstracted and at what layer the abstraction needs to exist. It also requires some perspective on common functionality within the APIs and from the point of view of the client code. Reusability and abstraction DO NOT exist in a vacuum and you can't simply make them up based on some general ideas of what constitutes an API's objects.
More generally speaking, creating an abstracted layer that can do D3D or OGL internally isn't about papering over whether it's a GLuint or an IDirect3DTexture* underneath. Those things are trivial, stupid issues. Some judicious use of the preprocessor and API specific files will solve those issues. No, the hard part in creating these abstractions is behavior and implied assumptions. There is a lot of devil in the details type stuff that can take some careful stepping to navigate. Simple example: OpenGL has the vertex array object (VAO), which encapsulates a client state (enabled attrib bits and bound VBOs). You'll have one per object, more or less. That doesn't exist in D3D 9. Instead there is a separate set of stream sources, and a vertex declaration which is typically shared heavily. It can get messier if you want to handle constant buffer APIs (D3D 11, GL 4.2). Render states are handled differently in GL than D3D9 than D3D11. And a nasty one for OpenGL based engines: D3D requires everything to be funneled through a device pointer, which is not necessary in GL. If your GL abstraction assumes it can change pipeline states without an external reference, you'll wind up patching in globals to support D3D. And this is all just a small slice.
It IS doable, and it is even doable with low level wrapping. But the lower level you get, the more intricate the behavioral details and implied assumptions become. More familiarity with the potential APIs (GL 2.x, GL 3.x, GL 4.x, D3D9, D3D11, D3D Xbox, PS3, etc) is needed. The advice to do the abstraction with very high level objects is a good one. It yields a fair bit of control to the underlying API and can create an annoying amount of duplicate or similar code across implementations. But it is more likely to be robust in the face of many different hardware APIs.